C++ C++;重载运算符、常量参数还是按值传递? 模板 T运算符+(T a,常数T&b){ a+=b; 返回a; } 模板 T运算符+(常数T&a、常数T&b){ T tmp{a}; tmp+=b; 返回tmp; }

C++ C++;重载运算符、常量参数还是按值传递? 模板 T运算符+(T a,常数T&b){ a+=b; 返回a; } 模板 T运算符+(常数T&a、常数T&b){ T tmp{a}; tmp+=b; 返回tmp; },c++,operator-overloading,parameter-passing,C++,Operator Overloading,Parameter Passing,既然您需要一个临时变量,那么您为什么要像第二个函数一样将参数作为常量引用传递,而不是像第一个函数那样直接传递值呢 编辑1: 我想我应该提到,这两个可选函数仅用于处理带有左值参数的case,我将提供另外两个用于处理带有右值参数的case的函数,如下所示 template <typename T> T operator+(T a, const T& b) { a += b; return a; } template <typename T> T o

既然您需要一个临时变量,那么您为什么要像第二个函数一样将参数作为常量引用传递,而不是像第一个函数那样直接传递值呢


编辑1:

我想我应该提到,这两个可选函数仅用于处理带有左值参数的case,我将提供另外两个用于处理带有右值参数的case的函数,如下所示

template <typename T>
T operator+(T a, const T& b) {
    a += b;
    return a;
}

template <typename T>
T operator+(const T& a, const T& b) {
    T tmp {a};
    tmp += b;
    return tmp;
}
模板
T运算符+(T&a,常数T&b){
a+=b;
返回std::移动(a);
}
模板
T运算符+(常数T&a、T&b){
b+=a;
返回std::move(b);
}
所以问题的重点是,为什么我需要显式地创建一个临时变量(函数2),而我可以让语言自动为我提供便利(函数1)?

模板
T运算符+(T a,常数T&b){
a+=b;
返回a;
}
在这里,您正在复制变量a,该变量在这里传递,然后您正在更新一个副本。这需要创建三个副本,并且再次按值返回

template <typename T>
T operator+(T a, const T& b) {
    a += b;
    return a;
}
模板
T运算符+(常数T&a、常数T&b){
T tmp{a};
tmp+=b;
返回tmp;
}
在这里,您的tmp变量有一个局部范围,变量a是常量引用,因此不允许修改a的值。 您将返回一个本地变量temp的副本

两者都很好,但区别在于创建的副本数量。您在第一种情况下制作的副本比第二种情况下多


尽管第二个变量将针对tmp变量进行优化,以使用移动语义来制作更少的副本。因此,在第二种情况下,您将有更快的性能

考虑
a+b+c
。当您通过值传递第一个参数时,您可以从
a+b
临时移动,当您通过const ref传递时,您不能。我个人更喜欢第一种方法。这就是说,如果性能真的很关键,那么您应该对用例进行基准测试,看看哪个用例最适合您。编译器将优化返回的副本以使用move语义i think@Mouse暗示,在第一个代码段中不允许使用NRVO,因为
a
也是一个函数参数。第二个片段消除了这一点。例如,第二个只做一个复制,第一个做一个复制,然后move@Bathsheba好电话。我忘了函数参数不符合RVO。第一个允许将子表达式的临时结果移动到lhs参数中。第二个总是在那里复制。与多余的举动相比,这可能是一种悲观。
template <typename T>
T operator+(T a, const T& b) {
    a += b;
    return a;
}
template <typename T>
T operator+(const T& a, const T& b) {
    T tmp {a};
    tmp += b;
    return tmp;
}