重载运算符:常量与非常量返回类型:任何性能差异
Overloading operators : const vs non-const return type : any difference of performance?
如果我们去维基百科关于C++运算符的文章,我们有一个例子:
Addition : a + b -> T T::operator +(const T& b) const;
因此,运算符返回一个类型 T 的非常量。如果我们看一下这个指南,作者说返回类型应该是一个常量以避免以下语法:
(a+b) = c
现在假设这种语法不会打扰我,并考虑 a 和 b 是大数组。从"纯"性能的角度来看,返回类型中缺少 const 关键字是否会阻止编译器(g++ 和带有 -O3 的英特尔 icpc)的优化?如果答案是"是",为什么?
这是一个有趣的问题。在 C++03 中,使用这两个选项中的任何一个进行优化都不会有更好的机会,这将是一个风格选择的问题(我自己不相信整个回报const
以避免不太可能的错误)。
另一方面,在C++11中,它实际上可能会产生影响。特别是,如果您的类型支持移动操作,并且无法省略返回值的复制/移出,则通过返回const
,您实际上禁用了移动 *
// T is move assignable, with the usual declaration of a move assignment operator
T f();
const T g();
int main() {
T t;
t = f(); // can move
t = g(); // cannot move!!!
}
在您的特定情况下,这取决于大型数组对您意味着什么,如果它们是std::array
的(或其他具有自动存储的数组),那么它们就无法移动,所以无论如何这都不是一个选项,但如果大型数组是动态分配内存的,移动将比复制更有效。请注意,在 C++11 中,存在而不是不存在可能导致性能损失的const
。
* 这不是 100% 正确的,如果移动赋值运算符通过右值引用将参数带到const
,那么它可以被移动。但是标准库中没有一种类型以这种方式接受参数,我也不期望人们这样做(它需要在移动操作(构造函数/赋值)内部const_cast
并且毫无意义:如果您打算从中移动(窃取),为什么您声称不修改它?
由于您返回的是 T
类型的临时 rvalue 实例,因此除非赋值操作中存在一些全局副作用,否则此语句不会执行任何操作,例如修改作为数据类型的数据成员的静态变量T
、输出到终端等。 因此,根据类型以及赋值运算符是否为编译器默认赋值运算符,可以在优化阶段中安全地省略整个操作。 如果类型 T
存在用户定义的赋值运算符,则不会省略赋值操作,但如前所述,除非存在全局副作用,否则这不会在语句执行的生命周期之后执行任何操作,因为您不会将 c
的值存储在驻留在命名和可访问内存位置的对象中。
请记住,如果您确实将返回T
类型声明为 const
,并且您的运算符方法不是 const
类方法,您将禁用某些类型的运算符链接,以及许多其他有用的东西,例如调用具有副作用的方法。 例如:
(a+b).print(); //assuming print() is non-const method
或者假设operator+
不是const
类方法,
d = (a+b) + c;
我会说永远不要将operator +
实现为成员函数。只需实现绝对不是常量operator +=
。然后你提供了一个全局函数来照顾operator +
,我认为这是最常见的方法。
T& T::operator +=(const T& t)
{
// add t to object ...
return *this;
}
T operator +(T t1, const T& t2)
{
t1 += t2
return t1; // RVO will eliminate copy (or move constructor)
}
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 什么时候在C++中返回常量引用是个好主意
- 代理对象的常量正确性
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- OpenMP阵列性能较差
- 通过多个头文件使用常量变量
- 递归列出所有目录中的C++与Python与Ruby的性能
- 在cuda线程之间共享大量常量数据
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 静态常量与常量局部变量,哪一个性能更好
- 通过常量引用传递基本值真的会损害性能吗?
- 静态、常量和全局变量带来的性能提升
- 重载运算符:常量与非常量返回类型:任何性能差异
- 传递常量引用:性能提高
- c++ -构造常量数据以提高性能和封装的方法
- 标记方法指针/引用参数常量真的会显著影响性能吗
- 函数参数中的常量基元类型是否会导致显著的性能提升?