如何在没有std :: move的情况下移动临时对象[复制]

问题描述 投票:4回答:2

这个问题在这里已有答案:

类的移动构造函数接受可以引用临时对象的rvalue引用。所以,我有临时对象和适当的移动构造函数,它可以接受对临时对象的引用,但是移动构造函数不会被调用。怎么了?

    //g++  5.4.0

#include <iostream>

class foo
{
    int data;
public:
    foo(int v) : data(v) {std::cout << "foo(int)\n";}

    foo(foo&& f)
    {
        std::cout << "moved\n";
    }

    void print()
    {
        std::cout << data;
    }
};

void acceptTmp(foo f)
{
    f.print();
}

int main()
{
    foo f1 = foo(100);
    f1.print();
    acceptTmp(foo(200)); //also does not move
}
c++ c++11 move-semantics copy-elision
2个回答
7
投票

怎么了?

没有什么是错的,除了你期望调用移动构造函数。

在C ++ 17之前,从抽象机器的角度来看,临时对象确实会被移入参数。但是,该标准允许编译器通过直接构造临时代替移动到的对象来省略移动。您不能依赖移动构造函数的副作用。

在C ++ 17之后,没有涉及临时对象或移动。该标准保证了参数的构建。


缺乏行动是一件好事。移动对象可能比不移动对象慢。


1
投票

通常,编译器通过应用as-if rule来执行优化和代码转换。复制/移动省略是“as-if”规则的唯一例外。即使存在副作用,编译器也会优化复制和移动操作,因为复制和移动操作需要付出代价。

当然在C ++ 17之前,它取决于编译器和可能的优化级别。但是从c ++ 17开始,保证了这一点。

如果要指示编译器不执行elision,可以使用-fno-elide-constructors编译器标志。

请参阅以下链接以了解有关复制/移动ellison的更多信息:

What are copy ellision?

© www.soinside.com 2019 - 2024. All rights reserved.