关键字 `this` 能在类作用域中使用吗?

6

似乎我可以在类作用域中定义捕获this的lambda表达式。根据我阅读的最新草案N4640,我没有找到允许这种行为的句子。我认为我可能漏掉了什么...

以下是一个示例:

#include <iostream>
#include <functional>

struct foo {
    std::function<void()> f1 = [this]{ ++i; };
    int i = 0;
};

int main() {
    foo a;
    foo const& cref = a;
    cref.f1();
    std::cout << a.i << std::endl;
}

运行演示。(g++ -std=c++11 pedantic) https://wandbox.org/permlink/HPzaOxbBkOQOmuS6

更新

感谢@Brian和@cpplerner的评论,我理解了我的核心问题。那就是“关键字this是否允许在类作用域中使用?不仅限于非静态成员函数作用域。” 如果可以,我可以在类作用域中的lambda表达式捕获列表中使用this。这很清楚。

似乎在类作用域中,this被视为非常量指针。

为了解决我的核心问题,我阅读了N4640 9.2.2.1 The this pointer [class.this]。从语法上讲,它似乎是允许的,但我找不到语义描述。对于非静态成员函数,我在9.2.2/3和9.2.2/4找到了语义描述。

更新

我更新了问题的标题以表示我的核心问题。

原始问题标题为在类作用域中,lambda表达式能否捕获this?


2
你认为不允许这样做的原因是什么? - Brian Bi
@Brian,我以为this只能在非静态成员函数中使用。但是看起来我错了。我写了另一个例子。https://wandbox.org/permlink/CUiG2KIOgD6q9qFy - Takatoshi Kondo
2
一个最小封闭范围为块作用域的lambda表达式是本地lambda表达式;任何其他lambda表达式在其lambda引入符中不得具有捕获默认项或简单捕获。 - cpplearner
3
你正在寻找expr.prim.this。@cpplearner 这是核心问题1632 - T.C.
@T.C. 谢谢您指出这个信息。那正是我在寻找的!! - Takatoshi Kondo
@cpplearner,我注意到我一开始误解了你的评论。但现在,我相信我理解正确了,并在我的回答中反映出来。 - Takatoshi Kondo
1个回答

1

自我回答的动机

感谢评论,我的问题得到了解决。我总结了使用评论回答问题的答案,以便其他人看到该问题。

关键字this可以在类作用域中使用吗?

可以。根据[expr.prim.this]

"关键字 this 指代非静态成员函数被调用时或者非静态数据成员初始化器([class.mem])求值时所调用的对象的指针。"

参见@T.C 's comment

关键字this能否在类作用域中的lambda表达式的捕获列表中写入?

不行。

至少在C++标准n4618的当前草案中,但C++标准委员会认为这是一个问题

以下是this不被允许的原因。

根据expr.prim.lambda

"一个最小封闭作用域为块作用域的lambda表达式是一个*本地lambda表达式;任何其他lambda表达式都不应该在其lambda引入符中具有捕获默认值简单捕获。"

类作用域中的lambda表达式不是局部lambda表达式。因为类作用域不是块作用域。这里是一词的定义。

因此,类作用域中的lambda表达式在其lambda引入符中不应具有默认捕获简单捕获

关键字this简单捕获之一。请参见expr.prim.lambda.capture

因此,在类作用域中的lambda表达式不能捕获this

请查看 @cpplearner的评论@T.C的评论

编译器实现

我在 g++ 和 clang++ 上测试了以下代码。

#include <iostream>
#include <functional>

struct foo {
    std::function<void()> lambda_in_class_scope = [this]{
        std::cout << this << std::endl;
    };
};

int main() {
    foo f;
    std::cout << &f << std::endl;
    f.lambda_in_class_scope();
}

输出:

0x7fff8f409cb0
0x7fff8f409cb0

我得到了相同的地址。这表明this被正确捕获。
这里是运行演示:
g++ 6.3 https://wandbox.org/permlink/FdhxJhVvripOQ1ng clang++ 4.0 https://wandbox.org/permlink/kGoNBIoV5WTZV0sy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接