运行这两个时我得到了不同的结果
我在GNU/Linux 4.14.67
这两个都在g++ -std=c++14
上/不使用-O0
的情况下以及在c++17
上运行。
我为什么?为什么输出不同?
第一个版本是:
#include <iostream>
#include <algorithm>
using namespace std;
class foo {
public:
foo() { }
foo(const foo& f) { }
foo& operator=(const foo& f) {
cout << "foo operator=\n";
val = 888;
// Do something important
return *this;
}
int val;
};
int main() {
foo f1;
foo f2;
f1 = f2;
cout << f1.val << endl;
}
第一个输出是:
foo operator=
888
第二个版本(仅将const foo&
更改为const auto&
):
#include <iostream>
#include <algorithm>
using namespace std;
class foo {
public:
foo() { }
foo(const foo& f) { }
foo& operator=(const auto& f) {
cout << "foo operator=\n";
val = 888;
// Do something important
return *this;
}
int val;
};
int main() {
foo f1;
foo f2;
f1 = f2;
cout << f1.val << endl;
}
第二个输出是:
0
答案 0 :(得分:5)
此:
foo& operator=(const auto& f);
在C ++ 20之前将不是标准的C ++代码。但是gcc已经允许了很长一段时间,这意味着:
template <typename _T>
foo& operator=(const _T& f);
换句话说,这是一个赋值运算符模板。它不是复制分配运算符。那一定是非模板的。由于您没有提供副本分配运算符,因此编译器会很高兴为您生成一个。在第一个代码示例中,您提供了自己的副本分配运算符。
写时:
f1 = f2;
在您的第一个示例中,该表达式有一个候选项:您编写的副本分配运算符。在第二个示例中,有两个个候选:您的赋值运算符模板和由编译器综合的副本赋值运算符。编译器的匹配更好(非模板Beats模板),因此它被调用-而不是您的。