多个参数时移动构造函数
move constructor when multiple arguments
我有一个类似这样的第一个构造函数
X::X(const std::vector<int>& v1, const std::vector<int>& v2, const std::vector<int>& v3) : _v1(v1), _v2(v2), _v3(v3){
} // _v1 , _v2 and _v3 are members
对于这种行为,我还应该实现移动构造函数版本
X::X(std::vector<int>&&, std::vector<int>&&, std::vector<int>&&);
但是可以像这样混合使用 const 左值引用和右值引用的参数类型
X::X(const std::vector<int>&, std::vector<int>&&, const std::vector<int>&);
是实现所有可能构造函数的最佳实践,即 2^3 ?
因为我们在这里讨论的是一个构造函数,所以按值获取参数并移动它们是相当有效的:
X::X(std::vector<int> v1, std::vector<int> v2, std::vector<int> v3)
: _v1(std::move(v1)), _v2(std::move(v2)), _v3(std::move(v3)) {}
根据实际参数,每个向量最多需要额外移动一次。但是移动很便宜,你不必编写 8 个单独的构造函数或一些不可读的 SFINAE 混乱。
请注意,如果您要进行 作业,则考虑因素会大不相同。复制构造 + 移动赋值可能比简单的复制赋值效率低得多,因为后者可能能够重用分配给对象所持有的资源。当您构建一个新对象时,这个因素不会发挥作用,因为没有资源可以重用。
或者按值传递向量,您可以采用转发引用:
template <typename T1, typename T2, typename T3>
X::X(T1&& v1, T2&& v2, T3&& v3) :
_v1(std::forward<T1>(v1)),
_v2(std::forward<T2>(v2)),
_v3(std::forward<T3>(v3))
{}
编辑:
如评论所述,缺点是它接受太多参数类型。在大多数情况下,向量构造函数会出错,但例如一个向量构造函数采用 int
,因此 X(42, std::vector<int>{42}, v3)
会起作用(v1
具有 42 个元素的向量 0
和 v2
1 个元素的向量 42
) 这可能是意外的。
SFINAE 可能会添加限制,但语法冗长。
我有一个类似这样的第一个构造函数
X::X(const std::vector<int>& v1, const std::vector<int>& v2, const std::vector<int>& v3) : _v1(v1), _v2(v2), _v3(v3){
} // _v1 , _v2 and _v3 are members
对于这种行为,我还应该实现移动构造函数版本
X::X(std::vector<int>&&, std::vector<int>&&, std::vector<int>&&);
但是可以像这样混合使用 const 左值引用和右值引用的参数类型
X::X(const std::vector<int>&, std::vector<int>&&, const std::vector<int>&);
是实现所有可能构造函数的最佳实践,即 2^3 ?
因为我们在这里讨论的是一个构造函数,所以按值获取参数并移动它们是相当有效的:
X::X(std::vector<int> v1, std::vector<int> v2, std::vector<int> v3)
: _v1(std::move(v1)), _v2(std::move(v2)), _v3(std::move(v3)) {}
根据实际参数,每个向量最多需要额外移动一次。但是移动很便宜,你不必编写 8 个单独的构造函数或一些不可读的 SFINAE 混乱。
请注意,如果您要进行 作业,则考虑因素会大不相同。复制构造 + 移动赋值可能比简单的复制赋值效率低得多,因为后者可能能够重用分配给对象所持有的资源。当您构建一个新对象时,这个因素不会发挥作用,因为没有资源可以重用。
或者按值传递向量,您可以采用转发引用:
template <typename T1, typename T2, typename T3>
X::X(T1&& v1, T2&& v2, T3&& v3) :
_v1(std::forward<T1>(v1)),
_v2(std::forward<T2>(v2)),
_v3(std::forward<T3>(v3))
{}
编辑:
如评论所述,缺点是它接受太多参数类型。在大多数情况下,向量构造函数会出错,但例如一个向量构造函数采用 int
,因此 X(42, std::vector<int>{42}, v3)
会起作用(v1
具有 42 个元素的向量 0
和 v2
1 个元素的向量 42
) 这可能是意外的。
SFINAE 可能会添加限制,但语法冗长。