由于C++中可以用两种方式声明复制构造函数,这是正确的方法吗?

由于C++中可以用两种方式声明复制构造函数,这是正确的方法吗?,c++,constructor,copy-constructor,C++,Constructor,Copy Constructor,假设你有以下课程: class Person{ string name; int age; int niNo; public: Person(const string & _name, const int & _age, const int & ni) : name(_name), age(_age), niNo(ni) {} string getName() const{ return name; }

假设你有以下课程:

class Person{
    string name;
    int age;
    int niNo;

public:
    Person(const string & _name, const int & _age, const int & ni) : name(_name), age(_age), niNo(ni) {}

    string getName() const{
        return name;
    }

    int getAge() const{
        return age;
    }

    int getNi() const{
        return niNo;
    }

    bool operator==(const Person &p){
        return name == p.getName() && age == p.getAge() && niNo == p.getNi();
    }
然后您可以按如下方式定义复制构造函数:

    Person (const Person &other){
        name = other.name;
        age = other.age;
        niNo = other.age;
    }
还是像这样

    Person (const Person &other) : name(other.getName()), age(other.getAge()), niNo(other.getNi()) {}

哪种方法最好?或者这不重要吗?

由于类是可复制构造的,最好的方法是使用C++11:

Person (const Person &other) = default;

否则,第二个更好,因为没有第一个默认的初始化和影响。

第二个更有效。在第一个示例中,成员名首先默认构造,然后分配。

一般来说,不仅仅是复制构造函数,最好直接在初始化器列表中初始化成员,就像第二个示例那样。第一个示例默认初始化它们,然后重新分配它们。这可能会降低效率,并且不适用于所有类型:它要求它们是默认的可初始化和可复制的,而直接初始化则不行


在这种情况下,如果您只需要一个简单的成员级副本,则根本不需要声明副本构造函数。隐式生成的一个将做正确的事情,并且不太容易出错,因为如果添加新成员,它不需要更新。

需要添加的一个重要方面。 如果您的私有数据成员中有一个是const,请说出name

您没有选项,必须在构造函数初始值设定项列表中初始化名称


如果它是常量,那么在进入构造函数主体之前它是默认构造的,并且您不能将它重新定义为常量…因此您必须使用您描述的两种方法中的初始值设定项列表,我强烈建议使用初始值设定项列表

当控件进入构造函数的主体时,标准规定对象在那个时候完全初始化,因此它的所有成员也必须初始化。您的第一个示例所做的是,它以某种默认方式初始化所有成员,然后稍后分配给它们

如果一个类成员是一个巨大的对象,这可能是无效的,如果一个成员在没有参数的情况下无法初始化,也就是说。E成员是常量、引用或没有默认构造函数的类


在这种情况下,必须使用初始值设定项列表自定义初始化过程。初始化器列表语法也可用于委托构造C++11和初始化基类。

问题是,可以用两种不同的方式声明它们,但所演示的两种声明都是相同的Person const Person&;我建议你阅读有效的C++,这是正确的,或者更好的是,不要声明它。为什么要添加不必要的杂波?@MikeSeymour:添加杂波的原因并不总是适用的,因为读取表示存在复制构造函数的显式代码要比查看类是否包含任何会阻止生成复制构造函数的内容更容易。@SteveJessop:True;如果您的类已经杂乱无章,以至于不明显,那么额外的杂乱无章可能弊大于利。不过,也许最好首先避免混乱。@MikeSeymour:我不认为拥有可复制性不明显的基类或数据成员构成混乱。但当然,如果您从类中删除无用的杂乱信息,如基类和类类型的数据成员,那么它们将更易于阅读-p或者,你当然可以将类记录为可复制的,这并不是说在C++11之前我们无能为力。@SteveJessop:我知道。不过这是一个意见问题,不值得争论。
class Person{
   const string name;
    int age;
    int niNo;
...