据我所知,当我们定义类的类复制构造函数时,Rule of three状态是必要的。我还注意到复制构造函数的参数通常是const
,如下面的代码所示:
class ABC {
public:
int a;
int b;
ABC(const ABC &other)
{
a = other.a;
b = other.b;
}
}
我的问题是如果复制构造函数的参数不是const会发生什么:
class ABC
{
public:
int a;
int b;
ABC(ABC &other)
{
a = other.a;
b = other.b;
}
}
据我所知,在某些情况下,如果复制构造函数的参数是const,那么第二个实现将失败。此外,如果复制构造函数的参数是const,则要复制的对象在此过程中不会更改其内容。但是,我注意到有些人仍然使用第二种实现而不是第一种实现。是否有任何理由认为第二种实施方式是首选的?
答案 0 :(得分:23)
从逻辑上讲,修改一个你只想制作副本的对象是没有意义的,虽然有时它可能有一些意义,比如你想存储这个时间的情况对象已被复制。但这可以使用存储此信息的mutable
成员变量,甚至可以修改const对象(第二点将证明这种方法的合理性)
您希望能够创建const对象的副本。但是如果你没有用const限定符传递你的参数,那么你就不能创建const对象的副本......
您无法从临时引用创建副本,因为临时对象是rvalue,并且不能绑定引用非const。有关更详细的说明,我建议Herb Sutter's article on the matter
答案 1 :(得分:11)
你的类的任何消费者都会期望的最后一件事是一个复制构造函数,它改变了被复制的对象!因此,您应始终标记为const。
答案 2 :(得分:8)
这里可能需要const有两个原因:
举例说明第二种情况:
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);
如果构造函数是ABC(ABC &other)
,则不会编译,因为a+a
是ABC类型的临时对象。但如果它是ABC(const ABC &other)
,我们可以使用计算的临时结果,并仍然将其作为参考传递。
答案 3 :(得分:5)
正如其他几个答案所指出的那样,修改其参数的复制构造函数将是一个令人不快的意外。然而,这不是唯一的问题。复制构造函数有时与 temporaries 的参数一起使用。 (示例:从函数返回。)对临时值的非常量引用不会飞,如SO elsewhere所述。
答案 4 :(得分:3)
如果复制构造函数未将其参数指定为const,则此片段将无法编译。
const ABC foo;
ABC bar(foo);
答案 5 :(得分:1)
复制构造函数不应修改正在复制的对象,这就是const
参数首选other
的原因。两者都有效,但const
是首选,因为它明确指出传入的对象不应被函数修改。
const
仅供用户使用。它不存在于实际的可执行文件中。
答案 6 :(得分:0)
它不是"必须"在技术意义上。我们甚至在标准中都有这样的野兽,但it got deprecated。请按照链接进行推理。
我们期望的副本的语义是离开"模板"在所有方面提供一个完全等同的克隆,你很难说出原始的形式。
如果有所期待,你应该三思而后行。它会给用户带来惊喜并可能引入错误。和沮丧和噪音,只是尝试谷歌的auto_ptr'矢量只是为了看点数。
问题的其余部分可能是"我发誓不要在实施中触及原文,但想要一个不同的签名"。什么签名呢?让我们试试T和T&amp ;.
由于需要复制ctor才能使用,因此我们就会失败,而我们正在实施这一点。递归:参见递归。离开T&amp ;.这实际上适用于一系列案件。但是如果你的原始对象碰巧以常量形式存在,或者是暂时的,那就失败了。为什么在没有下雨的情况下阻碍那个明智的案例?
答案 7 :(得分:0)
复制构造函数需要const
引用以避免无限循环。
class Cat
{
//code
Cat(Cat c)
{
//code
}
//code
};
调用复制构造函数时,它将创建对象c
,即它将执行类似Cat c = sourceObj
的操作。该语句应由副本分配运算符进行评估,但不是。这是因为c
尚不存在,因此必须进行。因此,该任务将交给复制构造函数。
无限循环!
我很惊讶没有人提到这个明显的原因。
其他原因:
sourceObj
答案 8 :(得分:-1)
除了复制构造函数不应修改源实例的基本假设之外,本文还详细阐述了使用 const 的实际技术原因:
http://www.geeksforgeeks.org/copy-constructor-argument-const/
即使我引用:
“...编译器创建的临时对象不能绑定到非const 引用......“