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