- 为什么使用大括号而不是括号来初始化句柄?
其他人已经说过花括号是什么(统一初始化),但没有人解释为什么在括号应该也能正常工作的情况下在这里使用它。
这个想法是,与其学习所有不同的初始化语法,C++11 使人们能够简单地学习一种语法并在任何地方使用它;统一初始化是为了更容易学习编写 C++(以及其他原因)而添加的功能之一。
需要注意的一点是,统一初始化是统一的,因为它适用于所有初始化上下文并且可以进行不同类型的初始化(例如,聚合初始化与使用构造函数),但这并不意味着可以进行任何初始化使用它; 具体来说,有一些极端情况可以定义类型,以便统一初始化无法访问某些构造函数。答案是根本不应该编写这样的构造函数。不幸的是,有些已经内置到标准库中,vector<int>(4, 5)
而vector<int>{4, 5}
不是常见的例子。
2. using module_handle = std::unique_ptr; 在这种情况下到底是什么意思?可以用typedef替换它吗?
这只是 typedef 的不同语法。该语法比 typedef 更强大,因为它可以被模板化,但是在这种情况下没有使用它。这个例子可以使用 typedef 来实现。
更喜欢新语法的原因是因为它是一种更加以类型为中心的、类似 C++ 的语法。
旧的 typedef 语法使用(据许多人说)受 C 的“声明模仿使用”规则的影响;也就是说,使用指针看起来像*ptr
,因此声明指针使用相同的表达式,int *ptr;
。使用返回指向函数的指针的函数看起来就像(*foo())()
再次声明使用相同的表达式,int (*foo())();
. 这种语法是以表达式为中心的,你写出一个表达式,语言推导出变量的隐含类型。
这种语法的问题在于它让很多人感到困惑,并且随着时间的推移,C 和 C++ 都发生了与最初的理想不一致的各种变化。例如,在 C 语言中声明一个函数最初就严格遵循此规则;在早期版本的 C 中,您可以声明一个与int foo(x, y)
函数调用表达式完全相似的函数foo(x, y)
。后来很明显,类型安全和检查很重要,并且在 ISO C 中声明一个函数看起来像int foo(int x, int y)
,它并没有那么紧密地模仿函数的用法。
C++ 更进一步,例如引入引用。由于引用用法看起来与使用常规对象没有任何不同,因此没有可以添加到声明中以遵循“声明模仿使用”的语法。相反,他们只是决定不遵守规则,而只是选择不会与之冲突的语法。
C++ 也比 C 更加强调类型。通过类型、基于类型的重载等参数化的模板。
因此,既因为旧语法似乎天生就有问题,又因为 C++ 更重视类型而不是表达式,C++11 为类型别名引入了这种新语法。它不是晦涩难懂的语法,而是简单明了的using <type alias> = <type>;
. 不需要“螺旋规则”或“从右到左”规则。
这种语法不仅可以完全替换 typedef,还增加了直接模板化的能力,替换了模板类 hack 中长期以来一直需要的旧 typedef。同样,新语法是一项附加功能,可以更轻松地学习编写 C++。