【问题标题】:C++ reference can be assignable?C++ 引用可以赋值吗?
【发布时间】:2018-01-12 00:58:22
【问题描述】:

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

#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)使用默认ctor创建FooWrapper fw,然后(2)从fw分配到fw2?我确定这不会发生,因为无法在未初始化的情况下创建引用,所以 fw2 的创建实际上是否被视为复制构造?

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

【问题讨论】:

    标签: c++ reference variable-assignment copy-constructor assignment-operator


    【解决方案1】:

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

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

    FooWrapper fw2;
    fw2 = fw;
    

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

    【讨论】:

      【解决方案2】:

      这个初始化实际上调用了复制构造函数。 FooWrapper fw2 = fw; 并且等价于 FooWrapper fw2(fw);

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

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

      【讨论】:

      • 是的,我就是这个意思。将措辞更改为implicitly defined copy constructor
      • 措辞也涉及这样一个事实,现在人们可以通过default关键字明确要求编译器生成一个复制构造函数:class_name ( const class_name &amp; ) = default;
      【解决方案3】:

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

      FooWrapper fw2 = fw;
      

      示例

      这是一个 (online) 示例,说明如何调用 default constructorcopy constructorcopy assignment operatormove 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
      }
      

      【讨论】:

        猜你喜欢
        • 2013-02-01
        • 2023-04-06
        • 1970-01-01
        • 2021-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-11
        • 1970-01-01
        相关资源
        最近更新 更多