upd*_*liu 9 constructor move c++11
class Foo {
std::vector<SomeType> data_;
};
Run Code Online (Sandbox Code Playgroud)
Say Foo只能通过制作一个对象的副本(技术上是指复制或移动)来std::vector<SomeType>构造.编写构造函数的最佳方法是Foo什么?
我的第一感觉是
Foo(std::vector<SomeType> data) noexcept : data_(std::move(data)) {};
Run Code Online (Sandbox Code Playgroud)
使用它,构造实例需要0或1次矢量复制,具体取决于{data}的参数是否可移动.
How*_*ant 17
你的第一感觉是好的.严格来说,这不是最佳选择.但它是如此接近最优,你说你不在乎是合理的.
说明:
Foo(std::vector<SomeType> data) noexcept : data_(std::move(data)) {};
Run Code Online (Sandbox Code Playgroud)
当客户端传入左值时,std::vector<SomeType>将使副本绑定到data参数.然后将进行1次移动以将"复制"参数data_.
当客户端传入xvalue std::vector<SomeType>1时,将移动绑定到data参数.然后将采取另一项举措,将论证"复制"进去data_.
当客户端传入prvalue时std::vector<SomeType>,移动将被省略绑定到data参数.然后将进行1次移动以将"复制"参数data_.
摘要:
client argument number of copies number of moves
lvalue 1 1
xvalue 0 2
prvalue 0 1
Run Code Online (Sandbox Code Playgroud)
如果您改为:
Foo(const std::vector<SomeType>& data) : data_(data) {};
Foo( std::vector<SomeType>&& data) noexcept : data_(std::move(data)) {};
Run Code Online (Sandbox Code Playgroud)
然后你的表现会略高一点:
当客户端传入左值std::vector<SomeType>1副本时,将复制参数data_.
当客户端传入xvalue std::vector<SomeType>1时,将进行"复制"参数data_.
当客户端传入prvalue std::vector<SomeType>1时,将进行"复制"参数data_.
摘要:
client argument number of copies number of moves
lvalue 1 0
xvalue 0 1
prvalue 0 1
Run Code Online (Sandbox Code Playgroud)
结论:
std::vector 移动结构非常便宜,特别是关于副本的测量.
当客户端传入左值时,第一个解决方案将花费您额外的费用.与必须分配内存的副本的成本相比,这可能是在噪声级别.
当客户端传入xvalue时,第一个解决方案将花费您额外的移动.这可能是解决方案的一个弱点,因为它会使成本翻倍.性能测试是确保这是或不是问题的唯一可靠方法.
当客户端传递prvalue时,两种解决方案都是等效的.
随着构造函数中参数的数量增加,第二个解决方案的维护成本呈指数增长.也就是说,您需要每个参数的const lvalue和rvalue的每个组合.这在1个参数(两个构造函数)中非常易于管理,在2个参数(4个构造函数)中更少,并且在此之后快速变得难以管理(具有3个参数的8个构造函数).因此,最佳性能不是唯一的关注点.
如果一个参数有很多参数,并且担心lvalue和xvalue参数的额外移动构造的成本,还有其他解决方案,但它们涉及相对丑陋的模板元编程技术,许多人认为这些技术太难看了(我不知道) ,但我试图不偏不倚).
因为std::vector,额外移动构造的成本通常很小,您将无法在整体应用程序性能中进行测量.