簡體   English   中英

在 C++ 中初始化變量的正確方法是什么

[英]What is the correct way to initialize a variable in C++

我有以下代碼:

bool c (a == b);

bool c {a == b};

其中 a 和 b 是一些相同類型的變量。

我想知道,以上兩種初始化有什么區別,在什么情況下應該首選哪一種? 任何形式的幫助將不勝感激。

兩種形式都是直接初始化

使用花括號{}進行初始化檢查縮小轉換並在發生此類轉換時生成錯誤。 不像() gcc 在這方面有問題,需要-Werror=narrowing編譯器選項才能在發生縮小時生成錯誤。)

花括號{}另一個用途是統一初始化:使用相同的語法初始化有和沒有構造函數的兩種類型,例如:

template<class T, class... Args>
T create(Args&&... args) {
    T value{std::forward<Args>(args)...}; // <--- uniform initialization + perfect forwarding
    return value;
}

struct X { int a, b; };
struct Y { Y(int, int, int); };

int main() {
    auto x = create<X>(1, 2);    // POD
    auto y = create<Y>(1, 2, 3); // A class with a constructor.
    auto z = create<int>(1);     // built-in type
}

使用花括號{}進行初始化的唯一缺點是它與auto關鍵字的交互。 auto {}推導出為std::initializer_list ,這是一個已知問題,請參閱 “Auto and braced-init-lists”

第一個是C++03風格的直接初始化。 第二個是 C++11 風格的直接初始化,它另外檢查縮小轉換。 Herb Sutter 在新代碼中推薦以下內容:

auto c = <expression>;

或者當你想提交到特定類型 T 時:

auto c = T{<expression>};

當 T 是某個具有重載構造函數的類時,大括號的一個已知缺點,其中一個構造函數將 std::initializer_list 作為參數,例如 std::vector:

auto v = std::vector<int>{10}; // create vector<int> with one element = 10
auto v = std::vector<int>(10); // create vector<int> with 10 integer elements

現在我們有五種形式的初始化。 他們是

T x = expression;
T x = ( expression );
T x (  expression );
T x = { expression };
T x { expression };

每種形式都有自己的特點。 :)

例如,假設您在全局命名空間中有以下聲明

int x;

void f( int x ) { ::x = x; }
int g() { return x ; }
long h() { return x; } 

然后在主要你可以寫

int main()
{
    int x ( g() );
}

此代碼將成功編譯。

然而,一個程序員錯誤地打錯了字

int main()
{
    int x; ( g() );
         ^^
}

哎呀! 此代碼也成功編譯。:)

但是如果程序員會寫

int main()
{
    int x = ( g() );
}

然后打錯字

int main()
{
    int x; = ( g() );
         ^^
}

那么在這種情況下,代碼將無法編譯。

好吧,讓我們假設程序員首先決定在初始化局部變量之前為全局變量 x 設置一個新值。

於是他寫道

int main()
{
    int x ( f( 10 ), g() );
}

但是這段代碼不能編譯!

讓我們插入等號

int main()
{
    int x = ( f( 10 ), g() );
}

現在代碼編譯成功!

那么大括號呢?

這段代碼也不行

int main()
{
    int x { f( 10 ), g() };
}

也沒有這個代碼

int main()
{
    int x = { f( 10 ), g() };
}

編譯!:)

現在程序員決定使用函數 h(),他寫道

int main()
{
    int x ( h() );
}

並且他的代碼編譯成功。 但過了一段時間他決定使用牙套

int main()
{
    int x { h() };
}

哎呀! 他的編譯器發出錯誤

錯誤:非常量表達式不能在初始化列表中從“long”類型縮小到“int”類型

程序決定使用類型說明符 auto。 他嘗試了兩種方法

int main()
{
    auto x { 10 };
    x = 20;
}    

int main()    
{
    auto x = { 10 };
    x = 20;
}    

和...一些編譯器編譯了第一個程序但沒有編譯第二個程序,一些編譯器沒有編譯這兩個程序。:)

那么使用decltype呢?

例如程序員寫的

int main()
{
    int a[] = { 1, 2 };
    decltype( auto ) b = a;
}    

而且他的編譯器發出了錯誤!

但是當程序員像這樣用括號括起來時

int main()
{
    int a[] = { 1, 2 };
    decltype( auto ) b = ( a );
}    

代碼編譯成功!:)

現在程序員決定學習OOP。 他寫了一個簡單的類

struct Int
{
    Int( int x = 0 ) : x( x ) {}
    int x;
};
    
int main()
{
    Int x = { 10 };    
}    

並且他的代碼編譯成功。 但是程序員已經知道有函數說明符explicit並且他決定使用它

struct Int
{
    explicit Int( int x = 0 ) : x( x ) {}
    int x;
};
    
int main()
{
    Int x = { 10 };    
}    

哎呀! 他的編譯器發出了一個錯誤

error: chosen constructor is explicit in copy-initialization

程序員決定去掉賦值符號

struct Int
{
    explicit Int( int x = 0 ) : x( x ) {}
    int x;
};
    
int main()
{
    Int x { 10 };    
}    

並且他的代碼編譯成功!:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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