C++ 当有多个参数时移动构造函数

C++ 当有多个参数时移动构造函数,c++,constructor,arguments,C++,Constructor,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(常量标准::向量和v1,常量标准::向量和v2,常量标准::向量和v3):\u v1(v1

我有一个像这样的第一个构造函数

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(常量标准::向量和v1,常量标准::向量和v2,常量标准::向量和v3):\u v1(v1),\u v2(v2),\u v3(v3){
}//\u v1、v2和v3是成员
对于这种行为,我还应该实现move构造函数版本

X::X(std::vector<int>&&, std::vector<int>&&, std::vector<int>&&);
X::X(std::vector&,std::vector&,std::vector&&);
但也有可能混合使用常量左值引用和右值引用的参数类型,就像这样

X::X(const std::vector<int>&, std::vector<int>&&, const std::vector<int>&);
X::X(const std::vector&,std::vector&,const std::vector&);

实现所有可能的构造函数(如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)) {}
X::X(std::vector v1、std::vector v2、std::vector v3)
:_v1(std::move(v1)),_v2(std::move(v2)),_v3(std::move(v3)){}
根据实际参数,每个向量最多需要额外移动一次。但是移动很便宜,而且你不必写8个单独的构造函数或者一些不可读的SFINAE乱七八糟的东西


请注意,如果你要做作业,考虑因素是完全不同的。复制构造+移动分配的效率可能远低于简单复制分配,因为后者可能能够重用分配给对象的资源。构建新对象时,此因素不会起作用,因为没有可重用的资源。

或者,要按值传递向量,可以采用转发引用:

模板
X::X(T1&&v1、T2&&v2、T3&&v3):
_v1(标准:正向(v1)),
_v2(标准:正向(v2)),
_v3(标准:正向(v3))
{}
编辑

作为注释中的状态,缺点是它接受太多的参数类型。在大多数情况下,向量构造函数会出错,但例如,一个向量构造函数使用
int
,因此
X(42,std::vector{42},v3)
可以工作(对于
v1
一个包含42个元素的向量
0
v2
一个包含1个元素的向量
42
),这可能是意外的


SFINAE可以添加限制,但语法冗长。

任何不将
X&&
作为其唯一参数的构造函数都不是move构造函数,它只是另一个常规构造函数。一般来说,如果你想优化这种类型的构造函数,你应该使用模板和完美的转发。一种可能是使用“通用引用”和sfinae来约束类型(一些),但我发现这有点模糊。为了补充这个答案,T.C.的评论是为什么您可能想要使用sfinae,但正如T.C.前面所说的(如您在中所见),它使代码变得丑陋。
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))
{}