我正在阅读一些c ++源代码,我找到了一些语法。
path& path::operator+=(string postPath)
我想知道它是否是实际语法以及为什么c ++没有使用已经存在的运算符+而是将值应用于相关对象。
是不是,如果你想确保对象被正确删除。但是析构函数应该处理所有这些。
-Edit1
我知道a + = b之间存在差异;和a + b;
我想知道为什么c ++不仅仅使用运算符+ + +而不必重新定义运算符+ =与运算符+
-Edit2
我不确定它是否正确,但我问的是为什么语言不能推断+ =基于+。 现在我意识到+ =的其他用途。谢谢大家:)
答案 0 :(得分:6)
C ++对重载运算符进行 no 假设;您可以
例如,定义一个不可交换的operator+
。你呢
可以定义与operator+=
无关的operator+
。
您还可以定义operator+=
而无需定义operator+
或副词
反之亦然。
至于为什么:对于初学者,你真的不希望编译器假设
字符串上的operator+
是可交换的,并因此进行优化。
一旦打开了门,这种语言的作者毫无疑问
觉得最好把它留给程序员,而不是
在语言层面强加任何东西。即使我无法想到一个案例
另一方面,可能存在支持+=
和{}的有意义的情况
+
语义略有不同。 C ++的一般哲学
一直以来都为程序员提供了他所需要的所有工具
写好的代码,但不要禁止不符合当前的代码
什么是坏代码的想法。 (从长远来看,这已经得到了回报,因为
我们关于什么是好的和坏的代码的想法已经发展。)
答案 1 :(得分:6)
可能存在效率问题;如果您的对象复制/分配成本高昂,a+=b
可能会为您节省临时构造,复制构造和分配,并允许您更好地利用目标对象中已有的资源。如果std::vector
有一个+=
运算符来连接向量,那么直接实现它会更有效(你可以利用目标对象的额外容量并避免无用的分配)而不是创建一个临时总和矢量(从头开始"从头开始")并分配它。
实际上,通常我会在+
方面实现+=
,通常会产生更高效,更容易编写的代码;像这样:
T &operator+=(const T &r)
{
// say that T encapsulates an N-dimensional array
for(int i=0; i<N; ++i)
arr+=r.arr[i];
return *this;
}
T operator+(const T &r)
{
T ret(*this);
ret+=r;
return ret;
}
(虽然我同意有一种方法可以让编译器从现有运算符合成+
/ -
;对于关系运算符也是如此)
您可能希望拥有一个可以添加但无法复制/分配的对象。例如,对于我的玩具项目,我简要地考虑过重载+=
以添加连接(Signal &operator+=(std::function<T...> fn)
)的信号对象(想想boost或Qt,或.NET事件/多播委托),但是我没有想要处理任务/复制语义(恕我直言,信号没有意义);
最重要的是,在C ++中你可以重载(几乎)所有运算符让它们做任何你想做的事情,而不受语义的特殊限制。您可以编写一个operator+
来启动火箭,一个operator+=
删除硬盘上的所有文件 - 您负责,如果在您的应用程序中有意义,您可以自由地执行此操作限制。
答案 2 :(得分:1)
是的,path& path::operator+=(string postPath);
有效,并且+=
运算符会因string
添加path
的情况而重载。
您希望能够重载它的原因很简单:operator+
必须返回新值而不是更改旧值,而operator+=
可以重用现有资源(例如分配的内存)。由于追加字符串的主要操作(您正在执行的操作)是内存分配,因此在您的确切情况下,+=
可以显着提高性能。
此外,操作SomePath + SomeString
提出SomeString + SomePath
的问题,更糟糕的是SomeStringA + SomePathB
,所有这些都略有不同,而SomePath += SomeString
具有非常明确的含义
由于现在很清楚为什么你希望能够在不实施+=
的情况下实施+
,请考虑另一个方向:为什么不使用{{1} }作为a = a + b
的默认实现:
首先,运算符重载规则早于a += b
。因此,即使在不希望= delete
存在的情况下,此规则也会始终触发。请注意,实现“默认”非常简单:
operator+=
答案 3 :(得分:0)
为什么c ++没有使用已经存在的运算符+而是结合应用值
正是因为+=
发生变异,而+
没有变异。这通常意味着实施方面的重大差异。
答案 4 :(得分:0)
将a += b
实现为a = a+b
的效率低于直接实现它,因为它必须创建和销毁分配给a
的临时对象。
根据+
+=
效率更高
path operator+(path prePath, string postPath) {
return prePath += postPath;
}
哲学上,人们可能会争辩说,如果语言没有神奇地产生你可能没想到的运算符,那就不那么令人惊讶了。许多人被隐式生成的构造函数和赋值运算符所捕获,给出了它们的类型无效的复制语义(直到他们学习Rule of Three),而其他魔法行为可能会在其他方面引起混淆。