在他的 GoingNative 2013 演讲中,Scott Meyers 指出,std::move
不能保证生成的代码会实际执行移动。
例子:
void foo(std::string x, const std::string y) {
std::string x2 = std::move(x); // OK, will be moved
std::string y2 = std::move(y); // compiles, but will be copied
}
在这里,不能应用移动构造函数,但由于重载决议,将使用普通的复制构造函数。这个回退选项可能对于向后兼容 C++98 代码至关重要,但在上面的示例中,它很可能不是程序员想要的。
有没有办法强制调用移动构造函数?
例如,假设您要移动一个巨大的矩阵。如果您的应用程序确实依赖于要移动的矩阵,那么在无法移动的情况下立即获得编译错误会很棒。(否则,您的性能问题可能很容易通过单元测试而溜走,只有在进行一些分析后才能发现。)
让我们称之为有保证的举动strict_move
。我希望能够编写这样的代码:
void bar(Matrix x, const Matrix y) {
Matrix x2 = strict_move(x); // OK
Matrix y2 = strict_move(y); // compile error
}
可能吗?
编辑:
感谢您的精彩回答!有一些合法的要求来澄清我的问题:
strict_move
如果输入是 const应该失败吗?- 如果
strict_move
结果不会导致实际的移动操作(即使副本可能与移动一样快,例如const complex<double>
),是否应该失败? - 两个都?
我最初的想法很模糊:我认为 Scott Meyers 的例子非常令人担忧,所以我想知道是否有可能让编译器阻止这种意外的复制。
Scott Meyers 在他的演讲中提到,一般编译器警告不是一种选择,因为它会导致大量误报。相反,我想与编译器进行交流,例如“我 100% 确定这必须始终导致移动操作,并且副本对于这种特定类型来说太昂贵了”。
因此,我会不经意地说这strict_move
两种情况都应该失败。同时我不确定什么是最好的。我没有考虑的另一个方面是noexcept
。
从我的角度来看,确切的语义strict_move
是开放的。任何有助于在编译时防止一些愚蠢错误而没有严重缺陷的东西都很好。