用花括号代替赋值操作符声明和实例化作用域变量



我正在观看Bjarne Stroustrup关于c++ 11风格的主题演讲(链接)(00:35:30),我在理解以下内容(从幻灯片复制的代码)时遇到了麻烦:

void f(int n, int x)
{
      Gadget g {n};
      // ...
      if (x<100) throw std::run_time_error{"Weird!"};
      if (x<200) return;
      // ...
}

我试着用一个结构体和一个对象来编译这段代码,但在这两种情况下,编译器都告诉我,它在Gadget g声明的末尾期待一个';',并且不会编译。

所以我的问题是:

  • 我假设g被实例化是正确的吗?
  • Gadget必须是什么类型的对象才能编译这个代码?
  • 这一行是什么概念在起作用:Gadget g {n}; ?也就是说,声明后面的花括号是什么?
  • (可能太宽泛了,但是)为什么编译器不能将花括号识别为有效语法?

我假设g正在被实例化是正确的吗?

是的,你是正确的。

Gadget必须是什么类型的对象才能编译这个代码?

任何可以从int初始化的类型。例如,如果你的Gadget类有一个接受int的构造函数,或者接受一些可以直接从int初始化的东西,这使得代码可以编译。

这行Gadget g {n};是什么概念在起作用?也就是说,声明后面的花括号是什么?

这是统一的初始化语法。它消除了括号符号的一些令人讨厌的问题,这些问题会使c++编译器将以下内容解析为函数声明(而不是对象的初始化):

struct Widget { /* ... */ };
struct Gadget { Gadget(Widget const&) { /* ... */ } /* ... */ };
Gadget g(Widget()); // This is parsed a FUNCTION DECLARATION

在上面的例子中,程序员的意图可能是构造一个Gadget类型的对象g,并从一个临时的Widget对象初始化它:然而,编译器会将其解析为一个名为g的函数的声明,该函数返回Gadget,并接受一个不接受参数并返回Widget的函数(指针指向a)。这就是所谓的最令人烦恼的解析问题。

注意,当使用大括号时,上面的问题不存在:

Gadget g{Widget{}}; // This could not be possibly parsed as a function declaration!

(可能太宽泛了,但是)为什么编译器不能将花括号识别为有效语法?

这很可能是因为您没有使用兼容c++ 11的编译器。您应该使用一个,并使用-std=c++11-std=c++0x编译标志来启用c++ 11支持。

最新更新