【问题标题】:C++11 lambdas can access my private members. Why?C++11 lambdas 可以访问我的私有成员。为什么?
【发布时间】:2014-08-05 22:13:46
【问题描述】:

考虑这段代码:

class shy {
private:
    int dont_touch;    // Private member

public:
    static const shy object;
};


const shy shy::object = []{
    shy obj;
    obj.dont_touch = 42;   // Accessing a private member; compiles; WHY?
    return obj;
}();


int main()
{
}

Live code (Clang)

Live code (GCC)

这对我来说似乎真的很不直观。 C++11/14 标准对此有何评论?这是 GCC/Clang 错误吗?

【问题讨论】:

  • 为什么这违反直觉...shy::object 的初始化表达式在类封装中,不是吗?
  • 可能是 3.4.1/13:用于定义 class X (9.4.2) 的 static 数据成员的名称(在 qualified-id 之后static 成员的名称)被查找,就好像该名称在 X 的成员函数中使用一样。
  • 考虑经典的 Meyers 单例由私有 ctor 初始化;这基本相同。
  • @TonyD 名称查找!= 可访问性
  • 可能是 9.4.2/2 “静态数据成员定义中的初始化表达式在其类 (3.3.7) 的范围内。” (乍一看,这似乎没什么新意)那段中的例子似乎同意。但更好的是关于静态数据成员的初始化程序可以访问什么的明确答案。

标签: c++ gcc c++11 lambda clang


【解决方案1】:

正如 cmets @Tony D@dyp 中已经回答的那样:

§ 9.4.2/2 静态数据成员 [class.static.data]:

中的初始化表达式 static 数据成员的定义在其类的范围内。

以上意味着static 数据成员及其初始化器可以访问其类的其他privateprotected 成员。

同时考虑标准§ 5.1.2/2&3 Lambda 表达式 [expr.prim.lambda]:

2 对 lambda 表达式的求值会产生一个临时右值 (12.2)。这个临时对象称为闭包对象。 lambda 表达式不得出现在未计算的操作数中(第 5 条)。 [注意:闭包对象的行为类似于函数对象(20.9)。-结束注释]

3 lambda 表达式的类型(也是闭包对象的类型)是唯一的、未命名的非联合类类型——称为闭包类型——其属性如下所述。此类类型不是聚合 (8.5.1)。闭包类型在包含相应 lambda 表达式的最小块作用域、类作用域或命名空间作用域中声明。

结合以上我们最终得出的结论是 您的 lambda 的纯右值临时闭包对象在 static const 数据成员 shy::object 的初始化程序中声明和定义,因此lambda 的闭包对象的范围是class shy 的范围。 因此它可以访问class shy 的私​​有成员。

【讨论】:

    猜你喜欢
    • 2014-03-13
    • 2016-10-26
    • 2012-07-23
    • 2021-06-29
    • 2012-09-24
    • 2011-01-06
    • 1970-01-01
    相关资源
    最近更新 更多