为什么复制构造函数的参数是const的?

33
 Vector(const Vector& other) // Copy constructor 
 {
    x = other.x;
    y = other.y;

为什么这个参数被声明为 const?


23
应该是 Vector(const Vector& other) : x(other.x), y(other.y) {}。了解初始化列表及其好处,请参阅:https://dev59.com/x3I-5IYBdhLWcg3w8dYQ。 - sbi
2
const-correctness 可能是一个你想要了解的术语。 - RichN
2
虽然它99%的时间是const,但也有反例;请参见std::auto_ptr。 - Mark Ransom
1
当然,auto_ptr已经被弃用了,因为即使是标准委员会的专家也没有完全搞清楚它。因此,我认为如果你发现一个复制构造函数的非const参数,你可以相当确定代码是有问题的。 - celtschk
8个回答

62

你已经得到了提到确保构造函数无法更改被复制的内容的答案,他们是正确的,放置const确实可以产生这种效果。

然而,更重要的是临时对象无法绑定到非const引用。复制构造函数必须接受对const对象的引用,才能够复制临时对象。


14
不仅限于临时对象 - 它还允许在标记为const的命名对象上使用复制构造函数。 - Michael Burr
这真的很令人困惑。你能告诉我“const Vector& other”和“Vector const &other”的区别吗? - Hoy Cheung
@HoyCheung:它们之间没有任何区别。 - Jerry Coffin
1
@HoyCheung 在编写代码时,更易读的方式是在你想要定义为const的类型后面加上const关键字。例如:int const * const可以创建一个指向常量整数的常量指针(声明符的反向阅读匹配你正在定义的类型)。但是第一个const(如果有的话)也可以放在前面(const int * const),我认为这是为了与C语言的原始版本兼容,或者仅仅是出于传统习惯。 - ABu

21
因为您不会修改作为const的参数other,所以在复制构造函数内部不会进行修改。
当您执行x = other.x时,它实际上意味着this->x = other.x。因此,您只是通过从变量other复制值来修改this对象。由于此处的other变量是只读的,因此将其作为const-ref传递。

10
通过告知调用者无需担心传入参数的更改,以及告知实现者不得更改该参数,这被认为是“良好的防御式编程”。 - Mark
18
这也是必要的,因为你希望能够将rvalue绑定到ctor的参数上: X x = f();。使用非const引用无法实现这一点。 - sbi

3
传统的复制构造函数和友元函数采用const&参数,原因如上所述。但是,您还应该查找移动语义右值引用(如果一切顺利,将成为C++0x的一部分),以了解何时使用不带const&参数的复制构造函数。另一个需要查看的地方是智能指针的实现,例如auto_ptr(具有所有权转移语义),其中非const参数很有用。

1
当我们尝试使用复制构造函数将一个对象复制到另一个对象时,我们需要保持原始对象的副本(即我们正在复制的对象),因此在传递对象时,我们将其设置为常量并按引用传递。

1

为了防止意外更改其他,该怎么做?


0

这不仅适用于复制构造函数。在任何函数中,如果您不打算修改对象的内部状态,则应将该对象作为const传递。

Vector(const Vector& other) 
{
     //Since other is const, only public data member and public methods which are `const` can be accessed.
}

由于Vector是一个Vector,所以你可以访问other的私有成员吗?如果你用OtherClass替换Vector参数,你就不能访问私有成员了。 - jamuraa
@jamuraa:你可以访问它们,但是不允许修改它们。试图修改会导致编译时错误。 - sbi

0

如果你只有一个常量引用,但想要复制一个对象,这也会很方便。

...
const Vector& getPosition();
...

Vector* v = new Vector(getPosition());

如果没有Vector(const Vector& other),该示例将会产生语法错误。

0
复制构造函数的概念是将“other”对象的内容复制到“this”对象中。const的作用是确保您不会修改“other”对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接