我正在尝试编写我的 vec 类。为了提高效率,我使用 move 语义。
Vec<int> v1;
Vec<int> v2;
Vec<int> v3;
Vec<int> v4;
v4 = v1 + v2; // Line 1
v4 = v1 + v2 + v3; // Line 2
v4 = v1 + (v2 + v3); // Line 3
但是,为了让上面的每一行只调用一次复制构造函数,我必须用一个运算符重载四个函数。喜欢下面的代码。
Vec(Myself&& v)
{ // move consturctor
dim = v.dim;
value = std::move(v.value);
}
Myself& operator+= (const Myself& v)
{
for (size_type i = 0; i < dim; ++i) (*this)[i] += v[i];
return *this;
}
template<typename std::enable_if<!std::is_reference<Myself>::value>::type* = nullptr> // SFINAE
friend Myself& operator+ (Myself&& a, const Myself& b)
{
return a += b;
}
Myself& operator+ (Myself&& v) const
{
return v += *this;
}
Myself operator+ (const Myself& v) const
{
Myself ansV(*this);
ansV += v;
return ansV;
}
感谢Lightness Races in Orbit的提醒。我在上面的代码中添加了 move 构造函数。
<强>1。有什么办法可以少写一个算子的函数吗?
<强>2。为什么在函数friend Myself& operator+ (Myself&& a, const Myself& b)
处添加SFINAE,而不是Myself& operator+ (Myself&& v) const
?用于修复v4 = v1 + (v2 + v3);
的混淆。
最佳答案
当我为算术类 T
编写运算符时,我通常会执行以下操作:
(a) 如果操作是可交换的(a+b 等于 b+a):
将+=
的实现放入T:
T & T::operator+=(T const& other) {
// [Perform the actual operation (add other to *this)]
x += other.x; // or something similar
return *this;
}
在类外提供如下两个函数:
T operator+(T a, T const& b) {
a += b;
return a;
}
T operator+(T const& a, T && b) {
MyInt temp(std::move(b));
temp += a;
return temp;
}
(b) 如果操作不可交换(a-b 不同于 b-a):
将 -=
的实现放入 T 并提供第二个函数,该函数作用于第二个操作数而不是第一个:
T & T::operator-=(T const& other) {
// [Perform the actual operation of (subtract other from *this)]
x -= other.x; // or something similar
return *this;
}
void T::operatorMinus(T & other) const {
// [Perform the actual operation, but work on other instead of *this]
other.x = x - other.x; // or something similar
}
在类外提供如下两个函数:
T operator-(T a, T const& b) {
a -= b;
return a;
}
T operator-(T const& a, T && b) {
MyInt temp(std::move(b));
a.operatorMinus(temp);
return temp;
}
结果:
在以下使用 -O3
的示例中,gcc 和 clang 现在只需要一个复制构造函数(与 operator-
相同):
T a1, a2, a3, x;
x = a1 + a2;
x = a1 + a2 + a3;
x = (a1 + a2) + a3;
x = a1 + (a2 + a3);
即使两个操作数都是右值的情况也不会产生歧义。以下编译正常,即使需要两个拷贝(a1+a2
一个拷贝,a3+a4
一个拷贝):
T a1, a2, a3, a4, x;
x = (a1 + a2) + (a3 + a4);
关于c++ - 在 C++ 中,有什么方法可以减少具有 move 语义的成员函数的数量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42345158/