c++中很少用到的构造函数语法

C++ what is this little used constructor syntax?

本文关键字:构造函数 语法 c++      更新时间:2023-10-16

编辑:我不认为这是另一个问题的重复,因为另一个问题只是在构造函数中将()调换为{}。然而,我注意到在struct中定义构造函数而不是在class中定义构造函数时的不同行为。(并且,正如在评论中指出的,这是关于使用构造函数而不是编写它们。)但是我以前也犯过错误。

我在辅导时遇到了这个构造函数的奇怪语法:

Foo obj {i, j};

起初我认为它不会工作,并告诉学生重写它-然而,他们坚持它的工作,并告诉我他们从cplusplus.com的例子,我没有能够找到一个参考,所以我试过了……这招奏效了。所以我尝试了一下。

我自己也研究了一下,在cplusplus.com上没有找到关于这种构造函数语法的参考。(也许它有一个特定的名称?)

这是我所做的实验。

struct Note { //A musical note.
    std::string name;
    double freq;
    //Note(std::string s, double f): name(s), freq(f){}
    //Uncomment the constructor in order to use normal constructor syntax.
};
class Journal {
public:
    std::string title;
    std::string message;
    int idNum;
};
int main() {
    Note a { "A", 440.0}; //Works with or without a constructor.
    //Note a("A",440.0); //Works ***only*** with a defined constructor.
    //Journal journal("hello, world", "just me, a class", 002); //Works regardless of constructor definition.
    Journal journal {"hello, world", "just me, a class", 003}; //Works regardless of constructor definition.
    std::cout << a.name << " " << a.freq << std::endl;
    std::cout << journal.title << " " << journal.message << " " << journal.idNum << std::endl;
    return 0;
}

我发现无论结构和类是否有定义的构造函数,它都可以工作。

显然默认构造函数在工作,但这让我感到困惑,因为几个原因:

  • 我以前从未见过这种语法(不奇怪,c++是巨大的)
  • 不管构造函数是如何定义的,所以可能是的默认行为
我的问题是:
  • 这种语法是否有一个名称和特定的目的,将它与常规的构造函数行为区分开来,如果是这样,为什么要使用它(或不使用)?

自c++ 11引入以来,情况发生了变化,您可能应该阅读有关列表初始化的内容

int x (0);  // Constructor initialization
int x {0};  // Uniform initialization

在引入它之前,您有各种初始化情况:

  • 对象通过调用通常的()构造函数(如果没有参数,请注意大多数令人烦恼的解析)
  • 用{}
  • 聚合类或数组
  • 默认构造,不带大括号

现在你可以使用统一的初始化。

需要注意的是,这两个是不能互换的,因为

std::vector<int> v (100); // 100 elements
std::vector<int> v {100}; // one element of value 100

,你必须注意这样一个事实:如果类型有初始化列表构造函数,它将优先处理重载解析。

也就是说,统一初始化可以非常方便和安全(防止窄化转换)。

这种语法称为"列表初始化"。你可以在c++ 14的8.5.4节中了解更多。

我猜这种语法的存在主要是为了向后兼容C语言,C语言中用于初始化结构体和数组的语法看起来非常相似。