无法理解零规则中的C ++ 11语法

时间:2013-11-12 21:48:06

标签: c++ c++11 idioms rule-of-zero

我正在研究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;
    };
  1. 为什么用括号括起来代替括号来初始化句柄?
  2. 使用module_handle = std :: unique_ptr是什么用法;在这种情况下是什么意思?是否可以用typedef替换它?

3 个答案:

答案 0 :(得分:7)

  

为什么要使用大括号而不是括号来初始化句柄?

这是C ++ 11中引入的uniform initializing方法

  

使用module_handle = std :: unique_ptr是什么用的;在这种情况下是什么意思?是否可以用typedef替换它?

它是template aliasing,也用于创建新类型。 usingtypedef

的全新替代品

答案 1 :(得分:3)

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基本相同。有关详细信息,请参阅this

答案 2 :(得分:3)

  
      
  1. 为什么用括号括起来代替括号来初始化句柄?
  2.   

其他人已经说过花括号是什么<(统一初始化)但是没有人解释为什么人们可以在这里使用它时括号应该也能正常工作。

这个想法是,C ++ 11不是学习所有不同的初始化语法,而是简单地学习一种语法并在任何地方使用它;统一初始化是为了更容易学习编写C ++而添加的功能之一(以及其他原因)。

需要注意的一点是,统一初始化是统一的,因为它可以在所有初始化上下文中工作,并且可以执行不同类型的初始化(例如,聚合初始化与使用构造函数),但这并不意味着任何初始化可以用它来完成;具体而言,有一些极端情况可以定义类型,使得统一初始化将无法访问某些构造函数。答案是,一个人根本不应该写这样的构造函数。不幸的是,有些内置于标准库中,vector<int>(4, 5)vector<int>{4, 5}是常见示例。

  

2。使用module_handle = std :: unique_ptr是什么用的;在这种情况下是什么意思?是否可以用typedef替换它?

这只是typedef的不同语法。语法比typedef更强大,因为它可以被模板化,但是在这种情况下不使用它。可以使用typedef实现此示例。

更喜欢新语法的原因是因为它是一种更加以类型为中心,类似C ++的语法。

旧的typedef语法使用(并且根据许多人使用)C的“Declaration mimics use”规则;也就是说,使用指针看起来像*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 ++更容易。