2

嘿,这是一个非常基本的问题,但我对此感到困惑。假设我创建了一个对象

MyObject a.

它带有一个复制构造函数,所以我知道我可以这样做:

MyObject b(a); 但我可以这样做吗?

MyObject& b(a);

如果我这样做:

MyObject b = a;里面有什么b?如果这个问题太基本而无法发布,请道歉。

4

2 回答 2

7

MyObject& b(a)与复制构造函数无关。它只是创建b了对 object 的引用a。没有任何东西被复制。将b其视为对象的别名a。从那时起,您可以等效地使用band来引用同一个对象。a

MyObject b = a;将使用复制构造函数,就像MyObject b(a);会一样。


初始化有两种形式:T x = a;称为复制初始化T x(a)并且T x{a}被称为直接初始化

何时T是引用类型,使用哪种类型的初始化并不重要。两者具有相同的效果。

T是类类型时,我们有两种可能:

  1. 如果初始化直接初始化(MyClass b(a);_ _ _ _aTMyClass b = a;T

    如您所见,您的两个示例都属于此类类型的初始化程序。

  2. 如果初始化是任何其他形式的复制初始化,则将考虑任何用户定义的转换序列,然后是直接初始化。用户定义的转换序列基本上是任何标准转换序列,其中包含一个转换构造函数。

    如果cFoo类类型并且有一个从Footo的转换构造函数MyClass,那么MyClass b = c;将等价于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;
}

该程序的输出(禁用复制省略)是:

Convert
----
Convert
Copy

当然,还有很多其他类型的初始化(列表初始化、字符数组、聚合等)。

于 2013-02-12T21:37:24.453 回答
0

这是我的看法:

引用与其他人的存储相关联,每当您访问引用时,您都在访问该存储。引用不能分配给 null 因为它们只是一个别名。引用必须在创建时进行初始化。(指针可以随时初始化。)

所以当你说

    MyObject& b(a);

编译器分配一块存储 b,并将引用绑定到 a。

当你说

    MyObject b = a;

您将 a 的引用传递给复制构造函数并从中创建新的 b 。请注意,仅当您为其编写了复制构造函数时,它才是深层副本。否则它会调用默认的复制构造函数,这会导致浅拷贝。

当你说

   a = b; // after creating these objects

它翻译为 Object::operator=(const Object&),因此 A.operator=(B) 被调用(调用简单复制,而不是复制构造函数!)

于 2013-02-12T22:02:30.557 回答