确保调用move构造函数
Making sure move constructor gets called
我有以下简化的代码示例:
#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构造函数被标准保证具有恒定的时间复杂性。问题是编译器是否遵守标准。我相信确保的唯一方法是调试或评测您的代码。
相关文章:
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 添加自定义析构函数时,Move 构造函数在派生类中消失
- 将向量从 N1 缩小到 N2 项,而不触发默认构造函数并仅使用 move 语义
- 为什么 std::move 不将默认移动构造函数中的源变量更改为默认值?
- std::映射,只有move构造函数可用
- 为什么我的代码中没有调用move构造函数
- std::转换move构造函数的模板专业化的变体
- std::tuple默认构造函数,带有move可构造元素
- 如何调用move构造函数
- 复制初始化:为什么即使关闭了复制省略,也没有调用move或copy构造函数
- 为什么我们需要在构造函数的初始化列表中使用 std::move?
- 在构造函数中初始化成员时,是否应该在成员上使用 std::move?
- 我可以将 std::move 与不提供 move 构造函数的类一起使用吗?
- 基于范围的 std::move 调用意外复制构造函数
- C++编译错误是由于使用 std::move 时运动构造函数与其他非运动构造函数之间的冲突
- 为什么noexcept move构造函数在向量重新分配期间没有被调用
- 使用 Move 语义在构造函数中初始化类成员
- 为什么在声明析构函数时必须声明 copy & move 构造函数?
- 我应该总是在构造函数中使用 std::move 吗?
- 如果我们只定义复制构造函数/oper=,为什么移动构造函数/move赋值没有隐式声明和定义为删除