我有以下堆栈类。
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。