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

时间:2018-09-06 10:38:33

标签: c++ c++11 move-semantics copy-elision

类的移动构造方法接受右值引用,该引用可以是临时对象的引用。因此,我有临时对象和适当的move构造函数,可以接受对临时对象的引用,但是未调用move构造函数。 怎么了?

    //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
}

2 个答案:

答案 0 :(得分:7)

  

怎么了?

没有什么错,除了您期望将调用move构造函数。

在C ++ 17之前,确实会从抽象机的角度将临时对象移到参数中。 但是,该标准通过直接构造临时对象来代替要移入的对象,从而使编译器可以忽略该移入。您不能依靠move构造函数的副作用发生。

在C ++ 17之后,不涉及任何临时对象或移动。该标准保证论点构造就位。


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

答案 1 :(得分:1)

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

当然,在C ++ 17之前,它取决于编译器以及优化级别。但是从c ++ 17开始,这种保证是有保证的。

如果要指示编译器不执行省略操作,则可以使用-fno-elide-constructors编译器标志。

请查看以下链接以了解有关复制/移动埃里森的更多信息:

What are copy ellision?