c++ - 在 C++ 中,有什么方法可以减少具有 move 语义的成员函数的数量吗?

标签 c++ move-semantics sfinae

我正在尝试编写我的 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/

相关文章:

C++ traits类检测成员函数: compiler error in MSVC 2015 RC

c++ - 无法在 Visual C++ ATL 项目中使用系统命名空间

c++ - 如何创建一个接收函数的函数,调用它并在 C++ 上返回它?

c++ - vector 构造函数标识为函数

c++ - 如果成员具有非平凡的 noexcept 赋值运算符,则默认 move 赋值不能显式地为 noexcept

c++ - 使用 enable_if 选择类构造函数

python - 构建 Numpy C++ 扩展;调用 PyArray_FROM_OTF 时出现段错误

c++ - 现在对临时工程的非 const 引用?

c++ - 因为 std::swap(s1, s2) 就足够了,所以 string::swap 可以忽略吗?

c++ - 检查 operator() 是否存在