编译器何时自动调用move语义?

时间:2019-05-27 13:23:23

标签: c++ move-semantics

我制作了一个测试程序来测试一些移动语义,请参见下文。

struct testcd
{
    int x;

    testcd(int i) : x(i) { std::cout << "constructor for " << i << "\n"; }
    ~testcd() { std::cout << "destructor for " << x << "\n"; }

    testcd(const testcd& cd) { std::cout << "copy constructor\n"; x = cd.x; }
    testcd(testcd&& cd) { std::cout << "move constructor\n"; x = cd.x; }

    testcd& operator=(const testcd& cd) { std::cout << "copy operator\n"; x = cd.x; return *this; }
    testcd& operator=(testcd&& cd) { std::cout << "move operator\n"; x = cd.x; return *this; }
};

testcd TestCD()
{
    std::cout << "- enter" << std::endl;

    std::vector <testcd> vec;
    std::cout << "- after empty vector" << std::endl;

    {
        testcd s(2);
        vec.emplace_back(s);
    }
    std::cout << "- after emplace back" << std::endl; 

    {
        testcd t(1);
        vec.push_back(t);
    }
    std::cout << "- after push back" << std::endl;

    for (auto&& t : vec)
    {
        std::cout << t.x << " ";
    }
    std::cout << "\n- after for &&" << std::endl;


    testcd c1(10);
    return c1;

}

int main()
{
    {
        auto cd = TestCD();
        std::cout << cd.x << std::endl;
    }

    _getch();
    return 0;
}

输出在这里:

- enter
- after empty vector
constructor for 2
copy constructor
destructor for 2
- after emplace back
constructor for 1
copy constructor
copy constructor
destructor for 2
destructor for 1
- after push back
2 1
- after for &&
constructor for 10
destructor for 2
destructor for 1
10
destructor for 10

有些事情仍然让我感到困惑:

  1. push_back和emplace_back看起来非常相似,复制构造函数用于两者。两者之间实际上有区别吗?

  2. 似乎在推送到容器(std :: vector)时,没有调用移动语义。唯一的方法是通过调用来强制执行此操作 vec.push_back(std::move(t));编译器可以看到临时值超出范围而没有被使用。

  3. 返回似乎按预期执行(某种)。没有优化,将调用move构造函数。通过优化,似乎只创建了一个对象,这两个方法都共享该对象,而没有移动或复制任何内容。但是,如果我返回使用std :: move,则会销毁Release优化,并且会额外调用move构造器+构造器+析构器。

所以我想知道:语言为什么不一致:推向向量要求我调用move(),返回要求我不要调用move()。看来我需要在每个编译器和每个用例中都进行测试,以便确保可以编写简单的最佳代码,并且这对初学者非常容易产生误导。

代码是使用VS2017 C ++ 17编译的,已在Release和Debug上进行了测试。

0 个答案:

没有答案