【问题标题】:difference between { } and equal sign variables{ } 和等号变量之间的区别
【发布时间】:2019-09-19 11:35:08
【问题描述】:

我对 C++ 编程有点陌生。我在谷歌的任何地方都找不到我的答案,所以希望可以在这里得到答案。

以下有区别吗

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;
        }
    }

}

【问题讨论】:

标签: c++ for-loop variables initialization list-initialization


【解决方案1】:

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

所有细节可以直接参考文档。

但是,我可以强调:

复制初始化比直接初始化更宽松:显式构造函数不转换构造函数并且不考虑复制初始化。

Initialization references here

对于unsigned int 类型(例如您的情况),两个初始化之间没有真正的区别。


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

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

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

即:

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

无法编译,因为您试图用浮点值初始化整数。

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

其实也可以这样写:

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

这是一个复制初始化,但使用花括号不允许缩小转换范围。

【讨论】:

    【解决方案2】:

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

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      考虑以下演示程序。

      #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&lt;int&gt;

      例如你可以重写你的循环

      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&lt;unsigned int&gt;

      所以通常你有以下形式的初始化

      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 .

      【讨论】:

        【解决方案4】:

        unsigned int counter = 1 ; 这种初始化风格继承自 C 语言。

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

        不同之处在于,如果您在使用 C++ 样式初始化时提供了错误的值 例如:

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

        但这不会给出任何错误。

        unsigned int counter = -1 ;

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-25
          • 2016-03-22
          • 1970-01-01
          相关资源
          最近更新 更多