提问人:oczkoisse 提问时间:3/8/2013 最后编辑:Jan Schultkeoczkoisse 更新时间:10/3/2023 访问量:50688
内置赋值运算符的返回类型是什么?
What is the return type of the built-in assignment operator?
问:
我刚刚开始C++。我对赋值和取消引用运算符的返回类型有点困惑。我正在阅读《C++入门》一书。在各种场合,作者说赋值运算符的返回类型是指左手操作数的类型,但后来,他说返回类型是左手操作数的类型。我参考了C++11标准第5.17节,其中返回类型被描述为“左手操作数的左值”。
同样,我无法确定取消引用是返回指向对象还是对对象的引用。
这些陈述是否等价?如果是这样,那如何?
答:
它们都可以是任何东西,但通常通过引用返回当前对象,即operator =
A& A::operator = ( ... )
{
return *this;
}
是的,“引用左手操作数的类型”和“左值引用左手操作数”的意思是一样的。
取消引用运算符基本上可以具有任何返回类型。这主要取决于程序的逻辑,因为您重载的是应用于对象的运算符,而不是指向该对象的指针。通常,这用于智能指针或迭代器,并返回它们环绕的对象:
struct smart_ptr
{
T* innerPtr;
T* smart_ptr::operator* ()
{
return innerPtr;
}
}
smart_ptr p;
T* x = *p;
评论
x = y
x
我见过类似的问题,但我想最好使用
X& X::operator=(const X&);
使用它,您将能够在链赋值中重用该对象。
该标准正确定义了赋值运算符的返回类型。 实际上,赋值操作本身并不依赖于返回值 - 这就是为什么返回类型不容易理解的原因。
返回类型对于链接操作非常重要。
请考虑以下构造:。这应该等于 ,即 应该分配到 和 into 。将其重写为 .为了使赋值正常工作,返回类型必须引用内部赋值结果(它也可以与复制一起使用,但这只是不必要的开销)。a = b = c;
a = (b = c)
c
b
b
a
a.operator=(b.operator=(c))
a
b.operator=(c)
取消引用运算符返回类型取决于您的内部逻辑,以适合您需求的方式定义它。
评论
链接工作,无需引用:从 operator= 返回副本仍然允许链接赋值(如 a = b = c),因为 operator= 将返回一个临时对象(已分配对象的副本),然后可以在后续赋值中使用该对象。但是,这涉及创建和销毁临时对象,这可能会产生性能开销,尤其是当这些操作对于相关类来说成本很高时。
正如Scott Meyers在他的《有效的C++》一书中提到的:
实现此方式是赋值返回对 它的左边论点,这是你应该遵循的惯例 当您为类实现赋值运算符时。这只是一个惯例;不遵循它的代码将编译。然而 所有内置类型以及 标准库中(或即将加入)中的所有类型 — 参见第 54 项 (例如,字符串、向量、复数、tr1::shared_ptr 等)。除非你有充分的理由以不同的方式做事,否则不要这样做。
下面的代码工作得很好!
#include <iostream>
class Rational {
public:
// ctor is deliberately not explicit; allows implicit int-to-Rational conversions
Rational(int numerator = 0, int denominator = 1)
{
this->m_numerator = numerator;
this->m_denominator = denominator;
}
int numerator() const // accessors for numerator
{
return this->m_numerator;
}
int denominator() const // accessors for denominator
{
return this->m_denominator;
}
Rational operator=(const Rational& rhs)
{
std::cout << "operator=(const Rational& rhs)\n";
this->m_numerator = rhs.m_numerator;
this->m_denominator = rhs.m_denominator;
return *this;
}
private:
int m_numerator{};
int m_denominator{};
};
int main()
{
Rational a(1, 2);
Rational b(3, 4);
Rational c(5, 6);
a = b = c; // a.operator=(b.operator=(c));
}
评论