{ }和等号变量之间的区别

6

我对C++编程有些新,无法在Google上找到答案,希望能在这里得到解答。

以下两个代码有何不同:

unsigned int counter{ 1 };

或者
unsigned int counter = 1;

这本书使用了第一种选项,但我感到困惑,因为它并没有解释两者之间的区别。以下是我正在遵循的书籍中的代码:

#include <iostream>
#include <iomanip>
#include <cstdlib> // contains function prototype for rand()
using namespace std;

int main()
{
    for (unsigned int counter{ 1 }; counter <= 20; ++counter) {
        cout << setw(10) << (1 + rand() % 6);

        // if counter is divisible by 5, start a new line of output
        if (counter % 5 == 0) {
            cout << endl;
        }
    }

}

4个回答

5
是的,它们是C++中两种不同类型的初始化。

有关所有详细信息,您可以直接参考文档。

但是,我可以强调:

复制初始化比直接初始化更严格:显式构造函数不是转换构造函数,也不适用于复制初始化。

此处有初始化引用

对于unsigned int类型(在您的情况下),这两种初始化没有实际区别。


注意 第一条语句中大括号的用法 (unsigned int counter{ 1 }) 提供了一个额外的约束条件:

否则 (如果 T 不是类类型),如果花括号初始化列表只有一个元素[...],T 直接初始化 [...],但不允许缩小转换

换句话说,在初始化中使用花括号不允许数据松散。

也就是说:

unsigned int counter{ 12.3 };  // error!!!

由于您试图使用浮点数值初始化整数,因此代码无法编译。

请注意,这是初始化中大括号的“属性”。它与初始化类型没有严格关联

事实上,您也可以这样写:

unsigned int counter = { 12.3 };  // error!

相反,这是一种复制初始化,但使用花括号不允许缩小转换。

1

unsigned int counter = 1 ; 这种初始化方式来自于C语言。

unsigned int counter {1} ; 这种初始化方式是C++的。

区别在于,如果你使用C++风格的初始化提供了错误的值,例如:

unsigned int counter {-1} ; 这将会出错(使用-std=c++11编译它)

但是这不会出现任何错误。

unsigned int counter = -1 ;


1

在其他解释的基础上,我会使用第一种选项(unsigned int counter{ 1 };)来初始化变量的值列表,对于单个值,我更喜欢使用第二种选项(unsigned int counter = 1;)

希望这能帮到你。


1
考虑以下演示程序。
#include <iostream>

struct A
{
    int x;
    explicit A( int x = 0 ) : x( x ) {}
};

int main()
{
    A a1 { 10 };
    std::cout << "a1.x = " << a1.x << '\n';

//    A a2 = { 10 };
}

在这个声明中
A a1 { 10 };

这里使用了直接初始化。

而在注释的声明中

//    A a2 = { 10 };

这可以被重写为:

也可以被重写为

//    A a2 = 10;

这里使用了复制初始化。但是构造函数的声明带有explicit关键字。因此,编译器会报错。这意味着无法将整数对象10隐式转换为类型A

你可以改为如下写法:

    A a2 = A{ 10 };

这是显式调用构造函数。

当然,对于基本类型来说没有区别,因为除了使用花括号初始化时不允许缩小转换之外,两个构造函数都不会被应用,例如:

int x { 1.0 };

当类型说明符为占位符auto时,存在很大的差异。
例如:
auto x = 10;

x的类型为int

auto x { 10 };

x 再次具有类型 int

auto x = { 10 };

现在,x 的类型是 std::initializer_list<int>
例如,您可以重写循环。
for (unsigned int counter{ 1 }; counter <= 20; ++counter) {

下面方式。
for ( auto counter{ 1u }; counter <= 20; ++counter) {

但是你可能不允许写。
for ( auto counter = { 1u }; counter <= 20; ++counter) {

因为在这种情况下,变量counter的类型是std::initializer_list<unsigned int>

因此,一般有以下形式的初始化:

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

例如
#include <iostream>

int main()
{
    int x1 = 1;

    std::cout << "x1 = " << x1 << '\n';

    int x2 = ( 2 );

    std::cout << "x2 = " << x2 << '\n';

    int x3( 3 );

    std::cout << "x3 = " << x3 << '\n';

    int x4{ 4 };

    std::cout << "x4 = " << x4 << '\n';
}    

程序输出为:
x1 = 1
x2 = 2
x3 = 3
x4 = 4

但是,当使用模板函数时,有一种情况需要使用T{}作为初始化器,而不是T()
考虑以下示例程序。
#include <iostream>

template <class>
void f()
{
    std::cout << "f<T>() is called\n";
}

template <int>
void f()
{
    std::cout << "f<int>() is called\n";
}

int main()
{
    f<int()>();
    f<int{}>();
}    

它的输出是:
f<T>() is called
f<int>() is called

int() 作为模板参数指定了类型模板参数 int,而 int{} 作为模板参数则指定了一个类型为 int、值为 0 的非类型模板参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接