1)有什么区别:
complex& operator = (const complex& c);
和
complex operator = (complex c);
2)如果我定义(在第二种情况下)复制构造函数,它们是否相同?
complex::complex (const complex& c){
//code
}
3) const 的作用是什么?
1)有什么区别:
complex& operator = (const complex& c);
和
complex operator = (complex c);
2)如果我定义(在第二种情况下)复制构造函数,它们是否相同?
complex::complex (const complex& c){
//code
}
3) const 的作用是什么?
你想要链式作业吗?返回*this
。
a = b = c; // Chained assignment
C++ 中的默认赋值支持链接,因此保留此规则是个好主意。
为了支持这种类型的赋值,每个操作都必须返回一个引用*this
或返回一个副本:
complex& operator = (const complex& c)
{
// do assignment
return *this;
}
或者
complex operator = (const complex& c)
{
// do assignment
return *this;
}
但是这个简单的工作应该是轻巧高效的。假设没有 RVO 或移动可用,则首选返回引用而不是副本。
我更喜欢返回引用的另一个原因是摆脱我脑海中令人困惑的事情。看这两种情况:
// Returning a reference
a = 1;
b = 2;
c = 3;
(a = b) = c;
任务完成后,a=3
b=2
c=3
。因为,首先b
分配给a
并返回对 的引用a
,然后c
分配给该引用并a
再次更改。
// Returning a copy
a = 1;
b = 2;
c = 3;
(a = b) = c;
任务完成后,a=2
b=2
c=3
。因为,首先b
分配a
并返回一个临时副本,然后分配给该临时对象(对orc
没有影响)。a
b
如您所见,结果是不同的。忽略发生了什么以及哪个更好。您应该选择一种对程序员来说很流行和期望的方式。我相信 C++ 程序员通过观看(a = b) = c
期待第一个结果。
因此,您应该使用第一个。
关于关键字const
:
当您通过对函数的引用传递对象时,该函数可以修改它。您可以放置一个const
来保护它免受不必要的更改。
1) 第一个是惯用的 C++ 版本。它说它需要对参数的引用(而不是复制),并将返回对通常是分配给的对象(即*this
)的复杂(而不是副本)的引用。
第二个可以工作,但它会产生不必要的副本,并且您不能在分配给的对象上调用函数,如下所示:(a = b).dosth()
因为它返回一个不同的对象。我的意思是它会编译,但它会调用dosth
一个临时对象。
2)它们从来都不一样,但是如果您没有可访问的副本ctor(或有时移动ctor),则第二个将不起作用。
3)const
是您不会修改参数的承诺。所以a = b
你不想修改b
和const
强制执行。您在第二个版本中不需要它(按值传递),因为无论如何您都无法修改它,因为它只是一个副本。
它们不一样,第一个传递引用,因此对象保留在内存中,第二个将需要copy-ctor,因为complex
对象将被复制进和复制出函数。第一个是规范的,你想要什么,第二个没有被使用,因为它是不必要的浪费。
这const
是一种说“我保证我不会改变c
!所以别担心!”的方式。这允许用户complex
通过引用提供实际的类(在您的情况下),而不必担心它会意外更改。
“引用”——通过添加&
符号选择——意味着这个函数实际上使用了用户给出的相同对象,来自相同的内存。由于它使用的是同一个对象,因此您承诺不会更改该对象很重要。
如果没有&
-您的第二个示例-您不会传递相同的对象,而是传递该对象的副本。所以这const
是不必要的(尽管仍然合法),因为用户不在乎您是否更改副本。
区别?时间(和大班的记忆)。如果您将引用传递给对象 - 您不需要复制该对象。这可以节省您的时间(复制对象所需的时间)和内存(对象需要的内存)。
第二种形式通过复制而不是通过引用获取和返回值,这通常是低效的。
complex operator=(complex c);
参数c
作为原始副本传入。对于像这样的简单数据类型int
无关紧要,但如果complex
是复杂的,这可能会导致不必要的分配/解除分配并影响性能。
通过引用传递,如:
complex& operator=(complex& c);
意味着传递给操作员的对象不会被复制。
第二个区别是他们返回的内容。运算符的正确形式是返回对自身的引用。您提供的第一个表单实际上返回了对象的副本,这同样可能是低效的。
最后,运算符的正确形式再次将输入对象作为const
参考。这更像是一个风格问题,而不是与性能有关的任何事情——但人们不会合理地期望赋值运算符修改输入对象,并将其指定为const
防止这种情况发生。
所以总结一下,
complex& operator=(const complex& c);
是正确的形式。