确保调用move构造函数

Making sure move constructor gets called

本文关键字:构造函数 move 调用 确保      更新时间:2023-10-16

我有以下简化的代码示例:

#include <algorithm>
#include <iostream>
using namespace std;
class ShouldBeMovedWhenSwapped
{
public:
//  ShouldBeMovedWhenSwapped() = default;
//  ShouldBeMovedWhenSwapped(ShouldBeMovedWhenSwapped&&) = default;
//  ShouldBeMovedWhenSwapped(const ShouldBeMovedWhenSwapped&) = default;
//  ShouldBeMovedWhenSwapped& operator=(ShouldBeMovedWhenSwapped&&) = default;
    struct MoveTester
    {
        MoveTester() {}
        MoveTester(const MoveTester&) { cout << "tester copied " << endl; }
        MoveTester(MoveTester&&) { cout << "tester moved " << endl; }
        MoveTester& operator=(MoveTester) { cout << "tester emplaced" << endl; return *this; } // must be declared if move declared
    };
    MoveTester tester;
};
int main()
{
    ShouldBeMovedWhenSwapped a;
    ShouldBeMovedWhenSwapped b;
    std::swap(a,b);
    return 0;
}

我使用的是MinGW,在运行"gcc——版本"时,我得到了gcc 4.7.2

编辑:关于第一个问题,请参阅问题中的注释。这似乎是gcc中的一个错误。

代码的输出取决于注释掉了哪些构造函数。但我不明白为什么会出现这种差异每次输出背后的原因是什么

// Everything commented out
tester moved 
tester copied <---- why not moved?
tester emplaced
tester copied <---- why not moved?
tester emplaced
// Nothing commented out
tester moved
tester moved
tester emplaced
tester moved
tester emplaced
// Move constructor commented out
tester copied
tester moved
tester emplaced
tester moved
tester emplaced

对于我的第二个问题(这就是我开始这个测试的原因)-假设我有一个带有大向量而不是类MoveTester的真实案例,在这种情况下,我如何确保向量被移动而不是被复制

问题的第一部分是一个过时的编译器,但还有另一个:您以次优的方式声明了MoveTester::operator=——它按值获取参数,因此复制/移动构造函数会被额外调用一次。尝试此版本的MoveTester:

struct MoveTester
{
    MoveTester() {}
    MoveTester(const MoveTester&) { cout << "tester copied " << endl; }
    MoveTester(MoveTester&&) { cout << "tester moved " << endl; }
    MoveTester& operator=(const MoveTester&) { cout << "tester copy assignment" << endl; return *this; } // must be declared if move declared
    MoveTester& operator=(MoveTester&&) { cout << "tester move assignment" << endl; return *this; } // must be declared if move declared
};

我得到以下输出:

tester moved 
tester move assignment
tester move assignment

也许即使使用GCC 4.7,您也会得到类似的结果。


关于您的第二个问题,std::vector的move构造函数被标准保证具有恒定的时间复杂性。问题是编译器是否遵守标准。我相信确保的唯一方法是调试或评测您的代码。

相关文章: