我已经完成了[问题](What's the difference between assignment operator and copy constructor?)并理解了复制构造函数和赋值运算符之间的区别。现在我的问题是虽然复制构造函数初始化以前未初始化的对象,其中赋值运算符替换先前初始化对象的数据最终结果的差异是什么。我认为两种情况下的最终结果都是一样的吗?在复制通过(CC)之后,我们获得相同的输出,甚至在使用(AO)之后我们得到相同的输出。我在这里有道理吗?有人可以澄清一下现实应用方面的区别吗?
答案 0 :(得分:2)
最终结果完全取决于具体情况。你只需要理解
从现有对象创建新对象时,将调用复制构造函数,作为现有对象的副本。
当两个对象都已创建并且我们正在将一个对象分配给另一个对象时,将调用赋值运算符。 例如: a = b
<强>差:强>
复制构造函数创建一个具有原始对象副本的新对象。
另一方面,赋值运算符不会创建任何新对象。相反,它处理现有的对象。
对于指针复制,我们需要深层复制作为编译器的默认复制构造函数,赋值运算符执行浅复制。因此,请查看此内容,以便更深入地了解Shallow copy vs Deep copy
答案 1 :(得分:1)
这取决于你。该语言没有任何要求
关于复制构造函数或赋值实际执行的操作。
当然,任何客户都会期望可观察到的状态
两者中的对象与复制对象的对象相同
例;这包括标准库中可能复制的代码
或分配给您的对象类型。但是有合法的案例
类可能包含用于的元信息
仪器或资源管理,可能会有所不同
在这两种情况下。 (一个班级也经常支持
复制构造,用于clone
函数,但不能用于
支持任务。)
当然,实施可能会有很大差异;如果 object包含一个指向动态分配的内存的指针 例如:
class Toto
{
Titi* myPtr;
public:
Toto() : myPtr( new Titi ) {}
Toto( Toto const& other ) : myPtr( other.myPtr->clone()) {}
~Toto() { delete myPtr; }
Toto& operator=( Toto const& other )
{
Titi* tmp = other.myPtr->clone();
delete myPtr;
myPtr = tmp;
return *this;
}
};
(在这种简化的情况下,当然,你不会使用
一个指针,只是让该类包含一个实例
Titi
。在一个更复杂的情况下,Titi
实际上是一个
抽象基类,并实例化不同的派生类
类根据构造函数的一些参数,
但是,这样的事情可能是合理的。)
答案 2 :(得分:0)
在复制构造函数中,您正在创建新对象,您正在从同一时间的其他对象为现有对象赋值。因此输出可能与实现复制构造函数和赋值运算符函数的方式不同
答案 3 :(得分:0)
除了你所说的,没有区别
CC适用于新的单元化对象(毕竟它是构造函数),是现有对象的运算符
CC的使用可以用普通的构造函数替换,然后是赋值op(在通常的类中),但这不如使用复制数据的直接构造那样有效。
例如
class C
{
private:
vector<int> v;
public
C()
{
//fill v with 10^9 slowly generated random numbers, takes ca. 2 days
}
C(const C& c) //could be auto-generated in this case
{
v = c.v;
}
C &operator=(const C& c) //could be auto-generated in this case
{
v = c.v;
return *this;
}
};
...
C oldc;
...
//either
C newc(oldc);
//or
C newc; //takes 2 days
newc = oldc;
另一个原因是,一些重要的类没有(公共)默认构造函数,只能通过从某处复制现有对象来创建。
答案 4 :(得分:0)
我确定你已经发现了很多关于复制构造函数和赋值运算符之间差异的帖子,或者至少是它们的默认行为(如果你超载它们,那么你可以做什么没有限制)做...或休息)。因此,我将限制我对您最终结果的具体问题的答案。
调用它们中的任何一个的结果是你最终得到了初始化(或重新初始化)的数据或对象......但是它还有更多,因为它们在不同的情况下被调用并且以不同的方式影响内存。没有深入讨论可能的不需要的行为,堆栈使用,浅层和深层复制(在处理指针时需要注意这一点),复制构造函数将创建一个对象的新实例并将数据复制到它,虽然赋值运算符使用并且已经存在的副本。
我希望这能回答你的问题...