簡體   English   中英

成員初始化器列表中的賦值操作

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM