未调用模板类复制构造函数
Template class copy constructor not called
我的复制构造函数没有被调用,我不知道为什么。这是我的代码:
template <typename T>
class SmartPtr
{
public:
explicit SmartPtr(T *p) : m_p(p) { cout << "ctor" << endl; }
SmartPtr(const SmartPtr& p) : m_p(p.m_p) { cout << "copy ctor" << endl;}
private:
T* m_p;
};
int main()
{
SmartPtr<int> pt4 = SmartPtr<int>(new int);
}
输出只是"ctor"。看起来使用了默认的复制构造函数。如果我添加"显式",那么它不会编译,给出错误:
"error: no matching function for call to ‘SmartPtr<int>::SmartPtr(SmartPtr<int>)’"
我在这里做错了什么?
这就是
所谓的复制Elision。这是一个很好的优化,显然不需要副本。而不是有效地运行代码:
SmartPtr<int> __tmp(new int);
SmartPtr<int> ptr4(__tmp);
__tmp.~SmartPtr<int>();
编译器可以知道__tmp
的存在只是为了构造ptr4
,因此允许在ptr4
拥有的内存中就地构造__tmp
,就好像最初运行的实际代码只是:
SmartPtr<int> ptr4(new int);
请注意,您也可以告诉编译器不要这样做。例如,在 gcc 上,您可以传递 -fno-elide-constructors
选项,并且通过该单个更改(另外记录析构函数),现在您的代码打印:
ctor
copy ctor // not elided!
dtor
dtor // extra SmartPtr!
请参阅演示。
在标准§12.8中:
在以下情况下允许这种复制/移动操作省略(称为复制省略),这些情况(可以组合以消除多个副本):
- 在具有类返回类型的函数的
return
语句中,当...- 在投掷表达式中,当...
- 当尚未绑定到引用 (12.2) 的临时类对象将被复制/移动时 对于具有相同 CV 非限定类型的类对象,可以省略复制/移动操作 将临时对象直接构造到省略的副本/移动的目标中
- 当异常处理程序的异常声明(条款 15)...
[示例:
class Thing { public: Thing(); ~Thing(); Thing(const Thing&); }; Thing f() { Thing t; return t; } Thing t2 = f();
在这里,可以组合省略的条件,以消除对类
Thing
的复制构造函数的两个调用: 将本地自动对象 t 复制到函数f()
的返回值的临时对象中 并将该临时对象复制到对象t2
中。有效地,本地对象的构建t
可以看作是直接初始化全局对象t2
,该对象的销毁将在程序中发生 退出。向 Thing 添加移动构造函数具有相同的效果,但它是从 临时对象到省略的t2
。—结束示例 ]
相关文章:
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 当从函数参数中的临时值调用复制构造函数时
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 复制构造函数、赋值运算符C++
- std::ofstream 作为类成员删除复制构造函数?
- 复制构造函数C++无法正确复制指针
- 关于复制构造函数的一个棘手问题
- 为什么调用复制构造函数而不是移动构造函数?
- 填充上编译器生成的复制构造函数之间的不一致
- C++ 对象指针数组的复制构造函数
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 防止在复制构造函数中隐式调用基构造函数
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 具有已删除移动和复制构造函数的类的就地构造
- 复制构造函数隐式转换问题
- 复制构造函数中的递归调用