我有下面的代码,看起来有些混乱。我定义了一个模板类。它具有用户定义的构造函数。当我通过“ operator =”声明此模板类的两个对象时,令其惊讶的是调用了它的用户定义构造函数。此外,删除其副本构造函数后,即使在解析“ operator =“的过程中,编译也无法通过。Templete构造函数的规则与非Templete类的规则不同吗?
#include "iostream"
using namespace std;
template <typename T>
class MyPtr
{
private:
T p_;
public:
MyPtr(T P = NULL): p_(P)
{
cout<<"track!!"<<endl;
}
//MyPtr(const MyPtr<T> & P) = delete;
~MyPtr()
{
}
};
int main()
{
int i=3;
int j=4;
MyPtr<int> p = i;
MyPtr<int> pp = j;
}
Templete构造函数的规则与非Templete类的规则不同吗?
不。
MyPtr<int> p = i;
(和MyPtr<int> pp = j;
)是复制初始化。请注意,这是初始化,而不是赋值,因为效果p
是由构造函数初始化的MyPtr::MyPtr(T)
。例如
MyPtr<int> p = i; // initialization; constructors get called
p = j; // assignment; assignment operators (operator=) get called
在C ++ 17之前,首先i
要MyPtr<int>
通过转换为MyPtr::MyPtr(T)
,然后将转换结果(即临时文件MyPtr<int>
被复制/移动以初始化)p
;即使允许复制/移动操作被优化,复制/移动构造函数也必须可访问。将复制构造函数声明为asdelete
会使复制构造函数不可用,并且将不会生成move构造函数,因此会导致格式错误,MyPtr<int> p = i;
直到C ++ 17为止。
由于C ++ 17的优化是强制性的,因此不需要再次访问copy / move构造函数,这意味着即使将copy构造函数声明为,您的代码也可以在C ++ 17模式下正常编译delete
。
- 如果T是类类型,并且other的cv不合格版本不是T或不是从T派生的,或者T是非类类型,但是other的类型是类类型,则用户定义的转换序列可以将其他类型转换为T(如果T是类类型并且可以使用转换函数,则可以转换为从T派生的类型),然后通过重载分辨率选择最佳的类型。转换结果(
prvalue temporary (until C++17)
prvalue expression (since C++17)
如果使用了转换构造函数,则为a)然后用于直接初始化对象。The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used. (until C++17)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句