简体   繁体   English

在 C++ 中初始化变量的正确方法是什么

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

I have the following code :我有以下代码:

bool c (a == b);

and

bool c {a == b};

where a and b are some variables of same type.其中 a 和 b 是一些相同类型的变量。

I want to know that, what is the difference in above two initializations and which one should be preferred in what conditions ?我想知道,以上两种初始化有什么区别,在什么情况下应该首选哪一种? Any kind of help will be appreciated.任何形式的帮助将不胜感激。

Both forms aredirect initialization .两种形式都是直接初始化

Using curly braces {} for initialization checks for narrowing conversions and generates an error if such a conversion happens.使用花括号{}进行初始化检查缩小转换并在发生此类转换时生成错误。 Unlike () .不像() ( gcc is buggy in this regard and needs -Werror=narrowing compiler option to generate an error when narrowing occurs.) gcc 在这方面有问题,需要-Werror=narrowing编译器选项才能在发生缩小时生成错误。)

Another use of curly braces {} is for uniform initialization : initialize both types with and without constructors using the same syntax, eg:花括号{}另一个用途是统一初始化:使用相同的语法初始化有和没有构造函数的两种类型,例如:

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
}

The only drawback of using curly braces {} for initialization is its interaction with auto keyword.使用花括号{}进行初始化的唯一缺点是它与auto关键字的交互。 auto deduces {} as std::initializer_list , which is a known issue, see "Auto and braced-init-lists" . auto {}推导出为std::initializer_list ,这是一个已知问题,请参阅 “Auto and braced-init-lists”

First one is the C++03 style direct initialization.第一个是C++03风格的直接初始化。 The second is C++11 style direct initialization, it additionally checks for narrowing conversions.第二个是 C++11 风格的直接初始化,它另外检查缩小转换。 Herb Sutter recommends the following in new code: Herb Sutter 在新代码中推荐以下内容:

auto c = <expression>;

or when you want to commit to specific type T:或者当你想提交到特定类型 T 时:

auto c = T{<expression>};

One known drawback with curly braces when T is some class with overloaded constructor, where one constructor gets std::initializer_list as parameter, std::vector for example:当 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

Now we have five forms of initializations.现在我们有五种形式的初始化。 They are他们是

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

Each of the forms has its own peculirities.每种形式都有自己的特点。 :) :)

For example let's assume that you have the following declarations in the global namespace例如,假设您在全局命名空间中有以下声明

int x;

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

then in main you can write然后在主要你可以写

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

This code will compile successfully.此代码将成功编译。

However a programmer by mistake made a typo然而,一个程序员错误地打错了字

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

Oops!哎呀! This code also compiles successfully.:)此代码也成功编译。:)

But if the programmer would write但是如果程序员会写

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

and then make a typo然后打错字

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

then in this case the code will not compile.那么在这种情况下,代码将无法编译。

Well let's assume that the programmer decided at first to set a new value for the global variable x before initializing the local variable.好吧,让我们假设程序员首先决定在初始化局部变量之前为全局变量 x 设置一个新值。

So he wrote于是他写道

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

But this code does not compile!但是这段代码不能编译!

Let's insert equality sign让我们插入等号

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

Now the code compiles successfully!现在代码编译成功!

And what about braces?那么大括号呢?

Neither this code这段代码也不行

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

nor this code也没有这个代码

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

compiles!:)编译!:)

Now the programmer decided to use function h(), He wrote现在程序员决定使用函数 h(),他写道

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

and his code compiles successfully.并且他的代码编译成功。 But after a time he decided to use braces但过了一段时间他决定使用牙套

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

Oops!哎呀! His compiler issues an error他的编译器发出错误

error: non-constant-expression cannot be narrowed from type 'long' to 'int' in initializer list错误:非常量表达式不能在初始化列表中从“long”类型缩小到“int”类型

The program decided to use type specifier auto.程序决定使用类型说明符 auto。 He tried two approaches他尝试了两种方法

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

and

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

and ...some compilers compiled the first program but did not compile the second program and some compilers did not compile the both programs.:)和...一些编译器编译了第一个程序但没有编译第二个程序,一些编译器没有编译这两个程序。:)

And what about using decltype ?那么使用decltype呢?

For example the programmer wrote例如程序员写的

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

And his compiler issued an error!而且他的编译器发出了错误!

But when the programmer enclosed a in parentheses like this但是当程序员像这样用括号括起来时

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

the code compiled successfully!:)代码编译成功!:)

Now the programmer decided to learn OOP.现在程序员决定学习OOP。 He wrote a simple class他写了一个简单的类

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

and his code compiles successfully.并且他的代码编译成功。 But the programmer has known that there is function specifier explicit and he has decided to use it但是程序员已经知道有函数说明符explicit并且他决定使用它

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

Oops!哎呀! His compiler issued an error他的编译器发出了一个错误

error: chosen constructor is explicit in copy-initialization

The programmer decided to remove the assignment sign程序员决定去掉赋值符号

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

and his code compiled successfully!:)并且他的代码编译成功!:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM