08 November 2022

C++ 核心指南目录

C.80: Use =default if you have to be explicit about using the default semantics

理由

编译器生成的默认操作,通常比自己手工实现的效果要好。

例子

class Tracer {
    string message;
public:
    Tracer(const string& m)
        : message{m} {
        cout << "entering " << message << '\n';
    }
    ~Tracer() {
        cout << "exiting " << message << '\n';
    }

    Tracer(const Tracer&) = default;
    Tracer& operator=(const Tracer&) = default;
    Tracer(Tracer&&) = default;
    Tracer& operator=(Tracer&&) = default;
};
int main()
{
    Tracer t{"hi"};
    Tracer k{"lo"};
    t = k;
}
entering hi
entering lo
exiting lo
exiting lo

因为我们定义了析构函数,所以我们必须定义复制和移动操作。用上 = default 是最好最简单的办法。

例子

class Tracer2 {
    string message;
public:
    Tracer2(const string& m)
        : message{m} {
        cout << "entering " << message << '\n';
    }
    ~Tracer2() {
        cout << "exiting " << message << '\n';
    }
    Tracer2(const Tracer2& a) : message{a.message} {}
    Tracer2& operator=(const Tracer2& a) {
        message = a.message;
        return *this;
    }
    Tracer2(Tracer2&& a) :message{a.message} {}
    Tracer2& operator=(Tracer2&& a) {
        message = a.message;
        return *this;
    }
};
int main()
{
    Tracer2 t2{"bonjour"};    
    Tracer2 k2{"halo"};
    t2 = k2;
}
entering bonjour
entering halo
exiting halo
exiting halo

手工编写拷贝和移动操作,又繁琐又麻烦,并且容易出错。还是交给编译器去处理吧。

强化

  • (一般)除非和编译器生成的操作一样,不然不要自己手动编写,画蛇添足。