为什么这些对象是通过复制而不是移动返回的?

Why are these objects returned by copy and not by move?

提问人:Gonen I 提问时间:4/3/2022 最后编辑:Gonen I 更新时间:4/3/2022 访问量:83

问:

为什么 getA() 和 getA2() 返回的值实例是使用 copy 构造函数而不是 move 构造函数返回的?

我正在使用 Visual Studio Community 2017,但 godbolt gcc/20 和 onlinegdb 给出了相同的结果。

struct A { 
    int *buff;
    A() {
        cout << "A::constructor\n";
        buff = new int[1000000];
    } 
    A(const A& a) {
        cout << "A::copy constructor\n";
        buff = new int[1000000];
        memcpy(buff, a.buff, 1000000*sizeof(int));
    }
    A(A&& original)
    {
        cout << "Move constructor" << endl;
        buff = original.buff;
        original.buff = nullptr;
    } 
    ~A() { cout << "A::destructor\n"; delete[] buff; }
};

A getA()
{
    A temp[1];
    temp[0].buff[0] = 7;
    return temp[0]; 
}

A getA2()
{
    A temp;
    A& temp2 = temp;
    temp2.buff[0] = 7;
    return temp2; // copy on return value
}
int main() {
    A copy = getA();  // calls copy instead of move
    A copy2 = getA2();  // also calls copy instead of move
}
C++ 复制构造函数 move-semantics

评论

0赞 prapin 4/3/2022
您是否在 C++17 或更高版本上编译?我建议您为正确的 C++ 标准版本添加标签。
0赞 Gonen I 4/3/2022
@prapin 使用 VS community 2017,在语言设置为 2014/2017/latest 时未检测到任何更改
2赞 user12002570 4/3/2022
无关:应使用而不是int main()void main()
0赞 Zereges 4/3/2022
尝试在启用优化的情况下编译它(使用/O2)
0赞 Eljay 4/3/2022
两者都不能被复制(RVO 或 NRVO),因为不符合这些约束。第一个是不移动结果;第二个也没有移动结果.所以复制就完成了。return std::move(temp[0]);return std::move(temp2);

答:

0赞 user12002570 4/3/2022 #1

如果目标是对语句进行移动构造,则可以通过使用 C++11 或 C++14 的标志进行编译来完成。A copy = getA();A copy2 = getA2();-fno-elide-constructors

演示

虽然来自海湾合作委员会

C++ 标准允许实现省略创建仅用于初始化相同类型的另一个对象的临时对象。指定此选项将禁用该优化,并强制 G++ 在所有情况下调用复制构造函数

所以我不确定为什么在您的情况下,此选项可以启用移动构造。这可能是一个错误或对我这边发生的事情的概念缺乏理解。因此,如果/需要时,我将删除此答案(一旦我知道为什么会发生这种情况)。

我无法将其放入评论中,因此在此处发布作为答案。