C++ 引用可以分配吗?

C++ reference can be assignable?

提问人:StoneThrow 提问时间:8/4/2017 最后编辑:JonasStoneThrow 更新时间:8/4/2017 访问量:836

问:

我一直在搞砸包装在容器类中的引用。为什么以下代码是合法的,并且看起来行为正确?

#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;
}

在没有明确的 的情况下,我相信 C++ 会做一个成员复制。所以当我这样做时,这不是两个操作吗:(1) 使用默认的 ctor 创建,然后是 (2) 从 到 的赋值?我确定这不会发生,因为引用不能在未初始化的情况下创建,那么创建实际上是否被视为复制构造?operator=FooWrapper fw2 = fw;FooWrapper fwfwfw2fw2

我有时不清楚文案构建与分配的作用;它们有时似乎会相互渗透,就像在这个例子中一样,但可能有一些我不知道的规则。我将不胜感激。

C++ 参考 变量 复制构造函数 赋值运算符

评论


答:

4赞 Jerry Coffin 8/4/2017 #1

尽管在语法中,copy 构造(使用 copy 构造函数)。既不涉及默认构造,也不涉及赋值。=FooWrapper fw2 = fw;fw2

并回答标题中的问题:不,不能分配参考文献。如果您编写的代码试图实际默认构造或赋值 ,例如:FooWrapper

FooWrapper fw2;
fw2 = fw;

...这将失败。正式地,只需要“诊断”。非正式地,我所知道的每个编译器都会/将拒绝编译它。

3赞 dau_sama 8/4/2017 #2

此初始化实际上调用复制构造函数。 并等同于FooWrapper fw2 = fw;FooWrapper fw2(fw);

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

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

评论

0赞 dau_sama 8/4/2017
是的,这就是我的意思。将措辞改为implicitly defined copy constructor
0赞 dau_sama 8/4/2017
措辞还涉及这样一个事实,即现在可以通过关键字明确要求编译器生成复制构造函数:defaultclass_name ( const class_name & ) = default;
4赞 Jonas 8/4/2017 #3

在下面的一行中,您通过使它成为 的副本来构造。也就是说,您正在调用 copy-constructor。fw2fw

FooWrapper fw2 = fw;

下面是一个(在线)示例,说明如何调用默认构造函数、复制构造函数复制赋值运算符和移动赋值运算符(来自 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
}