c++ - 确保 move 构造函数被调用

标签 c++ c++11 move move-semantics

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

#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 --version”时我得到 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

关于我的第二个问题(这就是我开始这个测试的原因)- 假设我有一个真实案例,其中有一个大 vector 而不是类 MoveTester,我如何确定 vector 被 move 而不是被复制 在这种情况下?

最佳答案

问题的第一部分是过时的编译器,但还有另一个问题:您以次优方式声明 MoveTester::operator= - 它按值获取参数,因此复制/move 构造函数被额外调用一次。试试这个版本的 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
};

我得到 the following output :

tester moved 
tester move assignment
tester move assignment

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


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

关于c++ - 确保 move 构造函数被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34404148/

相关文章:

c++ - 将全局 constexpr 类移动到类中作为静态 constexpr

class - PyBind11多种类型的模板类

c# - 将文件从一个目录 move 到另一个目录

c++ - 将命令模式、工厂模式和模板混合在一起......

c++ - 未解析的外部符号 OpenSSL 库 C++

c++ - 分配 vector 与指向 vector 的指针

c++ - 为什么将 std::move(object) 和此对象的成员传递给函数会导致 SIGSEGV

c++ - 在访问 vector<bool> 中的元素地址时获取临时地址

c++ - 为什么 std::array< T, 0 > 不为空?

python - 通过单击其中一个来 move 多个矩形