在 C++ 中,有什么方法可以减少具有移动语义的成员函数的数量吗?
In C++, is there any way to reduce the number of member functions with move semantics?
我正在尝试编写我的 vec class。为了效率,我使用移动语义。
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的提醒。我在上面的代码中添加了移动构造函数。
1.有什么办法可以少写一个算子的函数吗?
2。为什么在 friend Myself& operator+ (Myself&& a, const Myself& b)
函数中添加 SFINAE,而不是 Myself& operator+ (Myself&& v) const
?用于修复v4 = v1 + (v2 + v3);
.
的混淆
当我为算术 class 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;
}
在class之外提供以下两个函数:
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
}
在class之外提供以下两个函数:
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;
}
结果:
在以下示例中,gcc 和 clang 现在只需要一个复制构造函数,使用 -O3
(与 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);
我正在尝试编写我的 vec class。为了效率,我使用移动语义。
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的提醒。我在上面的代码中添加了移动构造函数。
1.有什么办法可以少写一个算子的函数吗?
2。为什么在 friend Myself& operator+ (Myself&& a, const Myself& b)
函数中添加 SFINAE,而不是 Myself& operator+ (Myself&& v) const
?用于修复v4 = v1 + (v2 + v3);
.
当我为算术 class 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;
}
在class之外提供以下两个函数:
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
}
在class之外提供以下两个函数:
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;
}
结果:
在以下示例中,gcc 和 clang 现在只需要一个复制构造函数,使用 -O3
(与 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);