简体   繁体   English

既然可以在C ++中以两种方式声明复制构造函数,那是正确的方法吗?

[英]Since you can declare a copy constructor in two ways in C++ which is the right way?

Say you have the following class: 假设您有以下课程:

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();
    }

And then you can define the copy constructor as follows: 然后,您可以如下定义副本构造函数:

    Person (const Person &other){
        name = other.name;
        age = other.age;
        niNo = other.age;
    }

or like this 或像这样

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

Which is the best way to do it? 哪种方法最好? Or does it not matter? 还是没关系?

As your class is trivially copy constructable, the best way is in C++11 : 由于您的类可轻松复制构造,因此最好的方法是在C ++ 11中:

Person (const Person &other) = default;

Otherwise, the second one is he better, because there is no default init and affection as in the first one. 否则,第二个比较好,因为没有第一个默认的初始化和喜好。

The second is more efficient. 第二个更有效率。 In the first, the member name is first default constructed and then assigned. 首先,首先默认构造成员name ,然后分配成员name

In general (not just for copy constructors) it's better to initialise members directly in the initialiser list, as your second example does. 通常,(不只是针对复制构造函数而言)最好像在第二个示例中那样直接在初始化程序列表中初始化成员。 The first example default-initialises them, then reassigns them. 第一个示例默认初始化它们,然后重新分配它们。 This is potentially less efficient, and won't work for all types: it requires that they be default-initialisable and copy-assignable, while direct initialisation doesn't. 这可能效率较低,并且不适用于所有类型:它要求它们是默认可初始化的和可复制分配的,而直接初始化则不能。

In this case, where you just want a simple member-wise copy, don't declare a copy constructor at all. 在这种情况下,如果只需要一个简单的成员级副本,则根本不要声明一个副本构造函数。 The implicitly generated one will do the right thing, and will be less error-prone since it doesn't need updating if you add new members. 隐式生成的成员将做正确的事,并且不会出现错误,因为如果添加新成员则不需要更新。

One important aspect to add. 要添加的一个重要方面。 If one of your private data members is const let's say name 如果您的私人数据成员之一是const,那么说一个name

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

You have no option and you must initialize name in the constructor initializer list! 您没有选择,您必须在构造函数初始化器列表中初始化名称!

If it is constant it has been default constructed before entering the body of the constructor and you can't redefine it as it constant...so there you must use the initializer list 如果它是常量,则在进入构造函数的主体之前已默认构造它,并且您无法将其重新定义为常量...因此必须在其中使用初始化程序列表

Of the two ways you described, I would strongly recommend using the initializer list. 在您描述的两种方法中,我强烈建议您使用初始化列表。

When control enters the body of your constructor, standards dictate that the object is fully initialized at that time, therefore all its members must be initialized as well. 当控件进入构造函数的主体时,标准指示该对象当时已被完全初始化,因此,其所有成员也必须被初始化。 What your first example does is that it initializes all the members in some default way and then assigns to them later. 您的第一个示例所做的是它以某种默认方式初始化所有成员,然后在以后分配给它们。

This is potentially ineffective if one of the class members is a huge object, and impossible to do if a member cannot be initialized without parameters, ie the member is a const , a reference, or is a class with no default constructor. 如果一个类成员是一个巨大的对象,则可能无效;如果一个成员没有参数就无法初始化,即成员是const ,引用或没有默认构造函数的类,则这可能无法实现。

In that case, you must use the initializer list to customize the initialization process. 在这种情况下,必须使用初始化程序列表来自定义初始化过程。 Initializer list syntax can also be used to delegate construction (C++11) and initialize base classes. 初始化程序列表语法也可以用于委派构造(C ++ 11)和初始化基类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM