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

我正在研究零规则,并对最后一段代码有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; 这意味着在这种情况下呢? 是否有可能用typedef替换它?

  • 为什么使用大括号来代替圆括号来初始化句柄?

    这是C ++ 11中引入的统一初始化方法

    什么使用module_handle = std :: unique_ptr; 这意味着在这种情况下呢? 是否有可能用typedef替换它?

    它是模板别名,也用于创建新类型。 usingtypedef的新的强大替代品


    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)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 ++更重视类型而不是表达式,所以C ++ 11为类型别名引入了这种新语法。 using <type alias> = <type>;而不是一个模糊的语法,这是一个简单的using <type alias> = <type>; 。 不需要'螺旋规则'或'从右向左'的规则。

    这个语法不仅可以完全替代typedef,而且还增加了直接模板化的能力,可以替代长期需要的模板类hack中的旧typedef。 再一次,新的语法是一个附加功能,可以使学习编写C ++变得更容易。

    链接地址: http://www.djcxy.com/p/78651.html

    上一篇: Trouble understanding the C++11 syntax in the Rule of Zero

    下一篇: Using fully qualified names in C++