使用auto作为成员函数参数时的不同结果

时间:2018-11-16 04:44:08

标签: c++ c++14 c++17

运行这两个时我得到了不同的结果

我在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

1 个答案:

答案 0 :(得分:5)

此:

foo& operator=(const auto& f);

在C ++ 20之前将不是标准的C ++代码。但是gcc已经允许了很长一段时间,这意味着:

template <typename _T>
foo& operator=(const _T& f);

换句话说,这是一个赋值运算符模板。它不是复制分配运算符。那一定是非模板的。由于您没有提供副本分配运算符,因此编译器会很高兴为您生成一个。在第一个代码示例中,您提供了自己的副本分配运算符。

写时:

f1 = f2;

在您的第一个示例中,该表达式有一个候选项:您编写的副本分配运算符。在第二个示例中,有两个个候选:您的赋值运算符模板和由编译器综合的副本赋值运算符。编译器的匹配更好(非模板Beats模板),因此它被调用-而不是您的。