为什么C++拷贝构造函数必须使用const对象?

fee*_*ree 18 c++ copy-constructor

我明白,当我们定义类的类复制构造函数时,必须作为三个状态的规则.我还注意到复制构造函数的参数通常const如下面的代码所示:

class ABC {
public:
    int a;
    int b;
    ABC(const ABC &other)
    { 
        a = other.a;
        b = other.b;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是如果复制构造函数的参数不是const会发生什么:

class ABC
{
    public:
    int a;
    int b;
    ABC(ABC &other)
    { 
        a = other.a;
        b = other.b;
    }
}
Run Code Online (Sandbox Code Playgroud)

我理解在某些情况下,如果复制构造函数的参数是const,那么第二个实现将失败.此外,如果复制构造函数的参数是const,则要复制的对象在此过程中不会更改其内容.但是,我注意到有些人仍然使用第二个实现而不是第一个实现.是否有任何理由认为第二种实施方式是首选的?

JBL*_*JBL 25

  • 从逻辑上讲,修改一个你只想制作副本的对象是没有意义的,尽管有时它可能有一些意义,比如你想要存储这个对象被复制的时间.但这可以使用mutable存储此信息的成员变量,甚至可以修改const对象(第二点将证明这种方法的合理性)

  • 您希望能够创建const对象的副本.但是如果你没有用const限定符传递你的参数,那么你就无法创建const对象的副本......

  • 您无法从临时引用创建副本,因为临时对象是rvalue,并且不能绑定引用非const.有关更详细的解释,我建议Herb Sutter关于此事的文章

  • 还有一个事实是采用非const引用的版本不适用于临时工. (5认同)

Bat*_*eba 11

你的类的任何消费者都会期望的最后一件事是一个复制构造函数,它改变了被复制的对象!因此,您应始终标记为const.


Mat*_*son 8

这里有两个可能需要const的原因:

  1. 它确保您在制作副本时不会意外地"损坏"原件 - 这是一件好事,因为您在制作副本时并不真的希望更改原始对象!
  2. 您可以传入除基本对象之外的其他内容 - 因为构造函数接受引用,如果它不是对象本身 - 例如表达式.

举例说明第二种情况:

 class ABC
    {
       public:
           int a;
           int b;
       ABC(const ABC &other)
       { 
         a = other.a;
         b = other.b;
       }
       ABC operator+(const ABC &other)
       {
           ABC res;
           res.a = a + other.a;
           res.b = b + other.b;
           return res;
       }
    }

  ...
  ABC A;
  a.a = 1;
  a.b = 2;
  ABC B(a+a);
Run Code Online (Sandbox Code Playgroud)

如果构造函数是ABC(ABC &other),则不会编译,因为它a+a是ABC类型的临时对象.但如果是ABC(const ABC &other),我们可以使用计算的临时结果,并仍然将其作为参考传递.


And*_*rus 5

正如其他几个答案所指出的那样,修改其参数的复制构造函数将是一个令人不快的意外.然而,这不是唯一的问题.复制构造函数有时与临时参数一起使用.(示例:从函数返回.)对临时值的非常量引用不会飞,如SO上其他地方所述.