难以理解零法则中的 C++11 语法
Trouble understanding the C++11 syntax in the Rule of Zero
我正在研究零法则,对演示该规则的最后一段代码有 2 个问题。
class module {
public:
explicit module(std::wstring const& name)
: handle { ::LoadLibrary(name.c_str()), &::FreeLibrary } {}
// other module related functions go here
private:
using module_handle = std::unique_ptr<void, decltype(&::FreeLibrary)>;
module_handle handle;
};
- 为什么使用大括号而不是括号来初始化句柄?
- 在这种情况下,使用 module_handle = std::unique_ptr<void,>; 到底是什么意思? 是否可以用 typedef 替换它?
为什么使用大括号而不是括号来初始化句柄?
这是 C++11 中引入的统一初始化方法
在这种情况下,使用 module_handle = std::unique_ptr; 究竟意味着什么?是否可以用 typedef 替换它?
它是模板别名,也用于创建新类型。 using
是 typedef
<</p>
explicit module(std::wstring const& name)
: handle { ::LoadLibrary(name.c_str()), &::FreeLibrary }
1) 这是 C++11 的新(统一)初始值设定项列表语法。 它将 2 个参数传递给构造函数,该函数将初始化变量 handle
。 在这种情况下,它实际上与
explicit module(std::wstring const& name)
: handle(::LoadLibrary(name.c_str()), &::FreeLibrary)
它将调用std::unique_ptr
的构造函数,该构造函数采用"指针"(在本例中为句柄)和删除器(FreeLibrary
的地址)。
using module_handle = std::unique_ptr<void, decltype(&::FreeLibrary)>;
2)这基本上与typedef相同。 有关详细信息,请参阅此处。
- 为什么使用大括号而不是括号来初始化句柄?
其他人已经说了大括号是什么(统一初始化),但没有人解释为什么当括号应该同样工作时,人们会在这里使用它。
这个想法是,C++11 不是学习所有不同的初始化语法,而是使人们能够简单地学习一种语法并在任何地方使用它;统一初始化是添加的功能之一,目的是使编写C++更容易(以及其他原因)。
需要注意的一点是,统一初始化是统一的,因为它适用于所有初始化上下文,并且可以执行不同类型的初始化(例如,聚合初始化与使用构造函数),但这并不意味着可以使用它完成任何初始化;具体来说,在少数情况下,可以定义类型,以便统一初始化无法访问某些构造函数。答案是根本不应该编写这样的构造函数。不幸的是,有些已经内置到标准库中,vector<int>(4, 5)
vs. vector<int>{4, 5}
是常见的例子。
2. 在这种情况下,使用 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++11 不仅因为旧语法似乎天生就有问题,也因为C++更重视类型而不是表达式,因此 11 为类型别名引入了这种新语法。而不是晦涩的语法,而是一个简单的using <type alias> = <type>;
。不需要"螺旋规则"或"从右到左"规则。
这种语法不仅可以完全替换 typedefs,还可以添加直接模板化的能力,替换长期以来需要的模板类 hack 中的旧 typedef。同样,新语法是一项附加功能,可以更轻松地学习编写C++。
- main.cpp(11):错误 C2059:语法错误:"字符串"
- 如何使用 c++11 语法创建 for 循环以遍历向量
- 语法在C 11中获取功能指针
- 哪些 gnu 属性具有 c++11 语法
- 是否有任何 DirectX 11 (HLSL 5.0) 等效于 DirectX 9 纹理"string function"语法?
- 使用新的 C++11 语法的 auto 进行函数声明,但使用 auto&并且没有 ->
- C++11 语法'type var : var'称为'range-based for'
- VS2010 和 VS2012 以及 C++11 错误 C2059:语法错误:"..."怎么走?
- 使用 C++11 迭代语法时从 STL 列表中删除
- vim 你完成了我在 C++11 语法上的错误
- 在C 11 /14语法中,是否有可能编写lambda函数,该函数将看到父变量
- GCC 4.4 不实现 C++11 范围循环.它还支持哪些其他范围循环语法
- 将gcc属性与C++11属性语法结合使用
- Doxygen 对 C++11 模板别名的支持("using"语法)?
- C++中循环语法糖的简写(11)
- C++11 regex_search和ECMAScript语法出现问题
- 难以理解零法则中的 C++11 语法
- Qt Creator c++11语法高亮显示通用项目
- 如何在c++ 11语法中初始化向量的向量
- 在Shift/Reduce解析器生成器中指定c++ 11语法动作函数