C++ 引用可以赋值吗?

C++ reference can be assignable?

我一直在处理包装在容器 类 中的引用。为什么以下代码是合法的并且表现得正确?

#include <iostream>

class Foo
{
public:
  Foo( int i ) : i_( i ) {}
  int i_;
};

class FooWrapper
{
public:
  FooWrapper( Foo& foo ) : foo_( foo ) {}
  Foo& foo_;
};

int main( int argc, char* argv[] )
{
  Foo foo( 42 );
  FooWrapper fw( foo );
  FooWrapper fw2 = fw;
  std::cout << fw2.foo_.i_ << std::endl;
  return 0;
}

在没有显式 operator= 的情况下,我相信 C++ 会进行成员复制。因此,当我执行 FooWrapper fw2 = fw; 时,这不是两个操作:(1) 使用默认构造函数创建 FooWrapper fw,然后是 (2) 从 fwfw2 的赋值?我确定这不会发生,因为无法创建未初始化的引用,因此 fw2 的创建实际上是否被视为复制构造?

我有时不清楚复制构造与赋值的作用;它们有时似乎会相互渗透,就像这个例子一样,但可能有一些我不知道的规则。我将不胜感激。

尽管语法中有 =FooWrapper fw2 = fw; 复制构造 fw2(使用复制构造函数)。根本不涉及默认构造和赋值。

并回答标题中的问题:不,无法分配引用。如果您编写的代码试图实际默认构造或分配 FooWrapper,例如:

FooWrapper fw2;
fw2 = fw;

...这会失败。正式地,只需要 "diagnostic"。非正式地,我知道的每个编译器 would/will 都拒绝编译它。

这个初始化实际上调用了拷贝构造函数。 FooWrapper fw2 = fw; 并且相当于 FooWrapper fw2(fw);

隐式定义的复制构造函数不需要创建未初始化的引用

供参考: http://en.cppreference.com/w/cpp/language/copy_constructor

在下面的行中,您通过复制 fw 来构建 fw2。也就是说,您正在调用复制构造函数。

FooWrapper fw2 = fw;

例子

这里调用了一个 (online) example on how default constructor, copy constructor, copy assignment operator, and move assignment operator (来自 C++11)。

#include <iostream>

struct foo
{
    foo() {std::cout << "Default constructor" << '\n';}
    foo(foo const&) {std::cout << "Copy constructor" << '\n';}
    foo& operator=(foo const&) {std::cout << "Copy assignment operator" << '\n'; return *this; }
    foo& operator=(foo &&) {std::cout << "Move assignment operator" << '\n'; return *this; }
};

int main( int argc, char* argv[] )
{
    foo a;            // Default constructor
    foo b = a;        // Copy constructor
    foo c;            // Default constructor
    c = b;            // Copy assignment operator
    b = std::move(c); // Move assignment operator
}