我有这个代码:
#include <iostream>
using namespace std;
class A{
char a;
public:
A(): a('#') { cerr << "DEFAULT!" << endl; };
A(char a): a(a) { cerr << "VALUE! " << a << endl; };
A(A const &o): a(o.a) { cerr << "COPY! " << o.a << endl; }
// A(A && o): a(std::move(o.a)) { cerr << "MOVE!: " << o.a << endl; }
// A(const A && o): a(std::move(o.a)) { cerr << "MOVE!(const): " << o.a << endl; }
// A(volatile A && o): a(std::move(o.a)) { cerr << "MOVE!(volatile): " << o.a << endl; }
// A(const volatile A && o): a(std::move(o.a)) { cerr << "MOVE!(const volatile): " << o.a << endl; }
// A(A && o) = delete; // (***)
friend A operator+(const A &o1, const A &o2){ A r; r.a = o1.a -'a' + o2.a; cerr << "+:" << r << endl; return r; }
friend ostream& operator<<(ostream& out, const A& o) { out << o.a; return out; }
};
int main(){
A a('a');
A b('b');
A c('c');
cout << a << b << c << endl;
A d(b+c); // <----- !!! WHO HANDLES THIS??? !!!
A e(a);
cout << a << b << c << d << e << endl;
return 0;
}
与“谁处理这个???”一致当值被正确传输时,奇迹就发生了。
我假设默认的移动构造函数被调用,所以我重载了它(然后是所有的 - 请参阅 4 行注释),但令我惊讶的是,没有人得到调用(如果未注释)。然后我尝试删除默认的复制构造函数(无论如何,根据https://en.cppreference.com/w/cpp/language/move_constructor,默认情况下不应创建它,因为我有复制构造函数)。这使得 g++/clang++ 在 WHO HANDLES THIS??? 中返回错误行,其中包含默认移动构造函数已删除的消息。 clang版本10.0.0-4ubuntu1,g++(Ubuntu 9.4.0-1ubuntu1~20.04.2)9.4.0.
这里到底发生了什么?谁能解释或指出任何规格?
如果将对象地址添加到跟踪输出中,HANDLER 会更容易查看。
这是由于 C++ 标准中允许的优化之一。有一天,C++ 标准甚至可能需要它。 (已更新,谢谢 Artyer。)
#include <iostream>
using std::cerr;
using std::cout;
using std::ostream;
class A {
char ch{ '#' };
public:
A() { cerr << "DEFAULT!\n"; }
A(char ch_) : ch{ch_} { cerr << "VALUE! " << ch << "\n"; }
A(A const& from) : ch{from.ch} { cerr << "COPY! " << ch << "\n"; }
friend auto operator+(A const& a, A const& b) -> A { A r; r.ch = a.ch -'a' + b.ch; cerr << "+:" << r << " @ " << &r << "\n"; return r; }
friend auto operator<<(ostream& out, const A& a) -> ostream& { return out << a.ch; }
};
int main() {
A a{'a'};
A b{'b'};
A c{'c'};
cout << a << b << c << "\n";
cout << "About to make a d...\n";
A d{b+c}; // <----- !!! WHO HANDLES THIS??? !!!
cout << "...d@" << &d << " has been made!\n";
A e{a};
cout << a << b << c << d << e << "\n";
}