我有以下代码使用-std=c++17
编译器通过编译标志-std=c++2@
和C++2@(GNU)
测试RVO
struct C
{
C() = default;
C(const C& obj){PrintAddress("copy ctor"); }
void PrintAddress( std::string mark = "") const { std::cout << "> " << mark << "\t" << this << '\n'; }
};
C get() { C c; c.PrintAddress("get()"); return c; }
int main()
{
C rvo = get();
rvo.PrintAddress("rvo's");
}
它输出:
> get() 0x7ffe7467db7c
> rvo's 0x7ffe7467db7c
但是,如果使用默认的副本构造函数:
struct C
{
C() = default;
C(const C& obj) = default;
void PrintAddress( std::string mark = "") const { std::cout << "> " << mark << "\t" << this << '\n'; }
};
输出变为:
> get() 0x7ffff37e7b4c
> rvo's 0x7ffff37e7bac //emmmm
复制省略已禁用。
基于reference,在以下情况下需要复制省略号:
在以下情况下,允许编译器,但即使复制/移动(自C ++ 11起)构造函数和析构函数也不需要省略类对象的复制和移动(自C ++ 11起)构造有明显的副作用。这些对象直接构造到存储中,否则会将它们复制/移动到其中。这是一种优化:即使发生并且未调用copy / move(由于C ++ 11)构造函数,它仍然必须存在并且可以访问(好像根本没有优化发生) ,否则程序格式不正确
所以,我的理解是没有复制构造函数,没有复制省略。我的问题是为什么呢?复制构造函数甚至不会在复制省略中调用。为什么必须提出?