重载赋值运算符和零规则

Overload assignment operator and rule of zero

我写了一个模板 class A<T> 我正在使用零规则(我让编译器生成析构函数,copy/move 构造函数和赋值运算符重载) . 但是,我现在需要一个自定义的赋值运算符,它采用不同类型 B<T> 作为参数:

A<T>& operator=(const B<T>& rhs);

此实现是否会阻止编译器生成默认析构函数等? 我的猜测是不,因为编译器生成

A<T>& operator=(const A<T>& rhs);

这与我想要实现的重载完全不同。

据我了解,添加operator=重载将不会阻止编译器根据0的规则生成默认值。

我的理解基于这样一个事实,即您的 operator= 重载实际上并不是 copy assignment, nor a move assignment。因此,关于生成默认构造函数和赋值运算符的规则不相关。

我用MSVC验证过了

您可以使用以下代码与您的编译器进行验证:

#include <iostream>

template <typename T>
struct B
{
    B(T const & n) : bn(n) {}
    T bn{ 0 };
};

template <typename T>
struct A
{
    A(T const & n) : an(n) {}
    A<T>& operator=(const B<T>& rhs)
    {
        an = rhs.bn;
        return *this;
    }
    T an{ 0 };
};

int main()
{
    A<int> a1{ 5 };
    A<int> a2{ 6 };
    std::cout << a2.an << ",";
    a2 = a1;    // Use default assinment
    std::cout << a2.an << ",";
    B<int> b{ 3 };
    a2 = b;     // Use custom assignment
    std::cout << a2.an << std::endl;
    return 0;
}

输出应该是:6,5,3:

6A<int> a2 构造的值,5 是从 A<int> a1 分配的值, 3 是从 B<int> b.

分配的值

注意: 另一种方法是使用 user-defined conversion function,正如@LouisGo 评论的那样(见上文)。