[英]Assignment operation in member initializer lists
我有以下堆棧類。
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]) {}
沒有。
Stack(const Stack& s) : x(new int[size=s.size]) {}
可以是
Stack(const Stack& s) : size(), x(new int[size=s.size]) {}
但這並不是真的,因為實際寫入size()
會對其進行值初始化,這意味着它被初始化為零,但是由於是初始化該合成的編譯器,所以發生了默認初始化[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
。 這給它留下了不確定的值(因為基本類型應該默認初始化)。 然后評估x
的初始化程序。 評估new int[size=s.size]
涉及賦值表達式size=s.size
,這會修改size
作為副作用。 因此,盡管可能引起您的注意,但您的代碼在這里是正確的。
當您切換成員的順序時,分配會在初始化size
之前進行。 這會使您的代碼開放給未定義的行為。
從關於構造函數的Cppreference.com頁面:
出現在expression-list或brace-init-list中的名稱在構造函數的范圍內進行評估:
所以,是的, size
這里指的是this->size
在構造函數的范圍和分配size=s.size
是有效的表達式。
不用說,您不應該期望它通過代碼審查:)
不,它將其重寫為:
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
沒有對象,因此它只是一個空語句,並且size
未初始化。 還是呢?
我會說這段代碼可能會產生未定義的行為。 成員變量按照10.9.2初始化基數和成員的聲明順序進行初始化 。 但是未定義用於初始化的表達式的求值順序。 因此,可以在 size()
之前或之后調用size=s.size
。對於類類型,這將是一個問題,但我不確定 size()
是否保證為無操作,以及編譯器是否可能決定將變量初始化為例如0。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.