4

这两个构造函数声明有什么区别:

class Fruit {
  private:
    int price;

  public:
    Fruit(int x): price(x)
    {
    }    
};

VS

class Fruit {
  private:
    int price;

  public:
    Fruit(int x)
    {
        price = x;
    }
};

我在继承的情况下看到的第一个。

据我所知,这不是一个重复的问题。如果你发现有人可以关闭这个问题。

4

4 回答 4

8

第一个用默认值初始化pricex第二个price用默认值初始化(默认构造它;如果是int变量,用未定义的值初始化),然后复制x.price

换句话说,第一个几乎等同于

int price = x;

第二个几乎等同于

int price;

price = x;

如果是int变量(也考虑编译器的优化),我想没有有效的区别。

但是,当price是一个复杂的对象,建设成本很高时,可能会有很大的不同。

正如彼得更好地解释的那样,“对于复杂对象,两者之间的区别并不是构造成本。这是一个问题,即在默认初始化后重新分配是否比一步初始化更昂贵。实际上,两阶段过程通常更昂贵(通过各种措施)而不是直接初始化,因为可能需要清理默认设置才能更改值。还有异常安全问题 - 如果重新分配或构造引发异常怎么办。

因此,通常强烈建议使用第一个解决方案(使用正确的值初始化对象)。

另请参阅 Zereges 的回答,该回答指出了第一个方法是唯一可用于将值分配给常量成员的事实。

确实写不出来

int const  price;

price = x;  // error: price is const
于 2018-11-10T22:33:36.843 回答
6

第一个使用初始化列表,而另一个不使用,并分配给构造函数体内的x数据成员。price

我们通常更喜欢使用初始化列表,并使构造函数的主体尽可能简单。

于 2018-11-10T22:27:46.747 回答
4

const要添加其他答案,第一个选项是初始化成员的自然方式

struct C
{
    const int val;

    C() : val(5) // Perfectly OK
    {
    }

    C(int) // error: uninitialized const member in 'const int' [-fpermissive]
    {
        val = 5 // error: assignment of read-only member 'C::val'
    }
};

此外,当类具有不可默认构造的类型成员时,这是初始化它们的方法

struct D
{
    struct not_default_constructible
    {
        not_default_constructible(int)
        {
        }
    } var;

    int& ref;

    D(int a) : ref(a), var(5) // Legal
    {
    }

    D(int a, char) // error: uninitialized reference member in 'int&' [-fpermissive]
    { // error: no matching function for call to 'D::not_default_constructible::not_default_constructible()'
        ref = a;
    }
};
于 2018-11-10T22:39:56.740 回答
3

第二个不会在创建a 时进行初始化price,因此默认构造它。就像你写的一样:xFruit

class Fruit{
private :
    int price

public:
    Fruit(int x) :
        price() // default constructed
    {
        price = x
    }    
}

为了有效起见,最好使用要分配给它的值进行初始化。

于 2018-11-10T22:35:05.787 回答