成员初始化器列表中的分配操作



我有以下堆栈类。

class Stack{
public:
    int size;
    int* x;
    Stack() : size(10), x(new int[10]) {}
    Stack(const Stack& s) : x(new int[size=s.size]) {}
};

请注意复制构造函数中的作业。该代码有效,即使使用-Wall -Wextra标志,编译罚款和编译器(GCC)也不会抱怨。编译器是否会自动将编译器重写为此?

Stack(const Stack& s) : size(s.size), x(new int[size]) {}

还是还有其他魔术?我注意到当我更改定义顺序时,编译器会投诉不订购初始化。所以我认为我提到的是这种情况。我在文档中找不到任何东西,ASM输出也没有帮助我。

编译器是否会自动将编译器重写为此?

Stack(const Stack& s) : size(s.size), x(new int[size]) {}

no。

Stack(const Stack& s) : x(new int[size=s.size]) {}

可以是

Stack(const Stack& s) : size(), x(new int[size=s.size]) {}

但不是真的,因为实际编写size()会重视初始化它,这意味着它是零初始化的,但是由于编译器合成了初始化,默认初始化 [1] [1] 就意义不是初始化的。然后,您在x的初始化中为其分配一个值。这是"安全的",这意味着在这种情况下它有效,但我不建议它。

Stack(const Stack& s) : size(s.size), x(new int[s.size]) {}

初始化两个成员,如果您在班级中更改它们的顺序,您仍然会有正确的行为。

类的成员总是按声明顺序初始化,无论您在成员初始化列表中指定的顺序如何。如果您省略它们,则它们是默认初始化的。这样做:

Stack(const Stack& s) : x(new int[size=s.size]) {}

表示size首先是默认的初始化。这使其具有不确定的值(因为基本类型应该是默认的initialized)。然后评估x的初始化器。评估new int[size=s.size]的一部分涉及分配表达式size=s.size,该表达式将size修改为副作用。因此,尽管可能会引起眉毛,但您的代码在这里是正确的。

当您切换成员的顺序时,应该在 size之前进行进行初始化。这使您的代码代码开放到未定义的行为。

从cppreference.com页面上的构造函数上的页面:

在构造函数的范围中评估了出现在表达列表或brace-init列表中的名称:

是的,size这里是指构造函数中的this->size,分配size=s.size是一个有效的表达式。

不用说您不应该期望这会通过代码评论:)

no,它将其重写为:

class Stack{
public:
    int size;
    int* x;
    Stack() : size(10), x(new int[10]) {}
    Stack(const Stack& s) :size(), x(new int[size=s.size]) {}
};

size()将是对象size的默认构造函数,但是int S没有一个,因此它只是一个空的语句,size仍然不进行初始化。还是它?

我会说此代码可能会产生未定义的行为。成员变量以根据10.9.2初始化基础和成员声明的顺序初始化。但是,用于初始化的表达式的评估顺序不是定义的。因此,size=s.size可以在size()之前或之后调用。对于可能是问题的类类型,但我不确定size()是否可以保证是无效的,以及编译器是否可以决定将变量初始化为例如。0。

最新更新