运行这两个时,我得到了不同的结果
我在 GNU/Linux 4.14.67
这两者都使用g++ -std=c++14
with/without -O0
和on 运行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;
}
Run Code Online (Sandbox Code Playgroud)
第一个输出是:
foo operator=
888
Run Code Online (Sandbox Code Playgroud)
第二个版本(仅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;
}
Run Code Online (Sandbox Code Playgroud)
第二个输出是:
0
Run Code Online (Sandbox Code Playgroud)
这个:
foo& operator=(const auto& f);
Run Code Online (Sandbox Code Playgroud)
在C++ 20之前,它不会是标准的C++代码.但是gcc已经允许了很长一段时间,它意味着:
template <typename _T>
foo& operator=(const _T& f);
Run Code Online (Sandbox Code Playgroud)
换句话说,这是一个赋值运算符模板.它不是复制赋值运算符.那必须是非模板.由于您没有提供复制赋值运算符,编译器很乐意为您生成一个.在您的第一个代码示例中,您提供了自己的复制赋值运算符.
当你写:
f1 = f2;
Run Code Online (Sandbox Code Playgroud)
在第一个示例中,该表达式有一个候选项:您编写的复制赋值运算符.在第二个示例中,有两个候选项:赋值运算符模板和编译器合成的复制赋值运算符.编译器是一个更好的匹配(非模板节拍模板),因此它被调用 - 而不是你的.