嘿,这是一个非常基本的问题,但我对此感到困惑。假设我创建了一个对象
MyObject a
。
它带有一个复制构造函数,所以我知道我可以这样做:
MyObject b(a);
但我可以这样做吗?
MyObject& b(a);
如果我这样做:
MyObject b = a;
b
中的内容是什么?道歉,如果这个问题太基础,不能打扰发布。
答案 0 :(得分:7)
执行MyObject& b(a)
与复制构造函数无关。它只是创建b
,它是对象a
的引用。什么都没有复制。将b
视为对象a
的别名。从那时起,您可以等效地使用b
和a
来引用同一个对象。
MyObject b = a;
将使用复制构造函数,就像MyObject b(a);
那样。
有两种初始化形式:T x = a;
称为复制初始化; T x(a)
和T x{a}
称为直接初始化。
当T
是引用类型时,使用哪种类型的初始化无关紧要。两者都有相同的效果。
当T
是类类型时,我们有两种可能性:
如果初始化是直接初始化(MyClass b(a);
),或者,如果它是复制初始化且a
正在进行派生自T
(MyClass b = a;
)的类型或类型:选择T
的适用构造函数来构造对象。
如您所见,您的两个示例都属于此类类型的初始化程序。
如果初始化是复制初始化的任何其他形式,则将考虑任何用户定义的转换序列,然后进行直接初始化。用户定义的转换序列基本上是任何标准转换序列,其中只有一个转换构造函数。
如果c
属于Foo
类类型且有Foo
到MyClass
的转换构造函数,那么MyClass b = c;
将等同于{{1} }}
基本上,如果源和目标类型相同,则两种形式的初始化都是等效的。如果需要转换,则不需要。一个简单的例子就是:
MyClass b(MyClass(c));
此程序的输出(禁用了复制省略)是:
#include <iostream>
struct Bar { };
struct Foo
{
Foo(const Foo& f) { std::cout << "Copy" << std::endl; }
Foo(const Bar& b) { std::cout << "Convert" << std::endl; }
};
int main(int argc, const char* argv[])
{
Bar b;
Foo f1(b);
std::cout << "----" << std::endl;
Foo f2 = b;
return 0;
}
当然,还有很多其他类型的初始化(列表初始化,字符数组,聚合等)。
答案 1 :(得分:0)
以下是我的观点:
引用与其他人的存储相关联,只要您访问引用,就会访问该存储。引用不能分配给null,因为它们只是一个别名。必须在创建引用时初始化引用。 (指针可以随时初始化。)
所以当你说
时 MyObject& b(a);
编译器分配一块存储b,并将引用绑定到。
当你说
时 MyObject b = a;
将a的引用传递给复制构造函数并从中创建新的b。请注意,只有在为其编写了复制构造函数时才会生成深层副本。否则,它会调用默认的复制构造函数,从而产生浅拷贝。
当你说
a = b; // after creating these objects
它转换为Object :: operator =(const Object&amp;),因此调用A.operator =(B)(调用简单副本,而不是复制构造函数!)