【问题标题】:copy constructor do not work in cpp template复制构造函数在 cpp 模板中不起作用
【发布时间】:2021-12-08 21:16:47
【问题描述】:

我正在写一个c++类型擦除的测试程序,代码放在最后。

当我运行程序时,测试用例 2 输出如下:

A default cstr...0x7ffe0fe5158f

obj_:0x7ffe0fe5158f objaaa 0x7ffe0fe5158f

Print A 0x7ffe0fe5158f

我的机器:Linux x86-64,gcc 4.8

在我看来,“对象 obj2(a2);”通过左值引用创建一个类模型,所以它应该调用 A 的复制构造函数, 但实际上它不起作用,这让我感到困惑。

谁能给个解释,先谢谢了。

节目列表如下:

#include <memory>
#include <iostream>
class Object {
public:
    template <typename T>
    Object(T&& obj) : object_(std::make_shared<Model<T>>(std::forward<T>(obj))) {
        
    }
    void PrintName() {
        object_->PrintName();
    }
private:
    class Concept {
    public:
        virtual void PrintName() = 0;
    };
    template <typename T>
    class Model : public Concept {
    public:
        Model(T&& obj) : obj_(std::forward<T>(obj)) {
            std::cout << "obj_:" << std::addressof(obj_) <<" objaaa "   << std::addressof(obj) << std::endl;
        }

        void PrintName() {
            obj_.PrintName();
        }

    private:
        T obj_;
    };
private:
    std::shared_ptr<Concept> object_;
};

class A {
public:
    A(A& a) {
        std::cout<< "A copy cstr...a" << this << std::endl;
    }
    A(A&& a) {
        std::cout << "A move cstr...." <<this<< std::endl;
    }
    A() {
        std::cout << "A default cstr..." <<this<< std::endl;
    }
    void PrintName() {
        std::cout << "Print A " << this << std::endl;
    }
};


int main(void)
{
    // test case 1
    Object obj{A()};
    obj.PrintName();

    // test case 2
    A a2;
    Object obj2(a2);
    obj2.PrintName();
    return 0;
}

【问题讨论】:

  • 复制构造函数的调用可以是elided
  • 是的,我认为你是对的,但是当我启用 compile(-fno-elide-constructors) 时,它仍然没有调用 copy cstr。
  • 没有复制。 T 被推断为A&amp;Objects 构造函数实例化了Model&lt;A&amp;&gt;,它将对a2 的引用存储为它的成员。注意std::addressof(obj_)a2的地址是一样的

标签: c++11 templates type-erasure


【解决方案1】:

Object obj2(a2); 中,没有复制。 Object的构造函数中的T被推导出为A&amp;,所以它实例化了Model&lt;A&amp;&gt;,它存储了对原始a2对象的引用作为它的obj_成员。

请注意,在您的调试输出中,a2 的构造函数、Model 的构造函数和 PrintName 都打印相同的地址。你可以进一步确认这个地址其实是&amp;a2

【讨论】:

    猜你喜欢
    • 2011-07-17
    • 1970-01-01
    • 2018-07-17
    • 2011-05-24
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    相关资源
    最近更新 更多