为什么复制构造函数的参数是引用而不是指针?
为什么我们不能使用指针呢?
答案 0 :(得分:13)
原因有很多:
引用不能为NULL。好的,可以创建一个NULL引用,但也可以将std::vector<int>*
转换为std::vector<SomeType>*
。这并不意味着这样的演员有定义的行为。并且都没有创建NULL引用。指针在设置为NULL时定义了行为;参考文献没有。因此,总是希望引用引用实际对象。
变量和临时变量不能隐式转换为指向其类型的指针。原因很明显。我们不希望指向临时运行的指针,这就是为什么标准明确禁止这样做(至少在编译器可以告诉你这样做的时候)。但我们可以向他们提供引用;这些是隐式创建的。
由于第2点,使用指针而不是引用会要求每个复制操作都使用地址运算符(&amp;)。哦等等,C ++委员会愚蠢地允许重载。因此,任何复制操作都需要实际使用std::addressof
(C ++ 11特性)来获取地址。因此,每个副本都需要看起来像Type t{std::addressof(v)};
或者您只能使用引用。
答案 1 :(得分:8)
这只是命名法。您也可以使用指针,但这被称为转换构造函数。
如果您考虑一下,这是有道理的,因为您将一个对象复制到另一个对象(而不是“复制”)。不是指向对象的指针。如果它是一个指针,它就不会复制,因为你没有将指针复制到对象,而是指针指向对象的对象。
答案 2 :(得分:5)
因为标准拒绝了这一点。
引用C ++草案标准n3376 - 第12.8.2节:
如果第一个参数的类型为 X&amp;,const X&amp ;,则X类的非模板构造函数是一个复制构造函数, 挥发性X&amp;或const volatile X&amp; ,并且没有其他参数或其他所有参数 有默认参数
答案 3 :(得分:5)
为什么它应该是一个指针?空指针没有意义。 使用指针不允许复制临时工,所以你 无法做到这样的事情:
MyClass
func()
{
// ...
return MyClass(...);
}
你可以定义一个带指针的构造函数。但事实并非如此 是一个复制构造函数,因为它不能用于像 以上。它不会阻止编译器生成 复制构造函数。
答案 4 :(得分:1)
因为指针可能是nullptr
,必须检查它,而临时指针不能指向它们。
答案 5 :(得分:1)
通过引用传递确保将实际对象传递给复制构造函数,同时指针可以具有NULL值,并使构造函数失败