gpt4 book ai didi

C++11:防止 lambda 作用域捕获错误

转载 作者:行者123 更新时间:2023-12-04 12:52:36 24 4
gpt4 key购买 nike

在 C++ 中,与 C# 等语言相比,可以指定是否应通过值或在 lambda 表达式中的引用来捕获封闭作用域变量。这会导致未定义的情况,在这种情况下,可以通过引用在调用 lambda 表达式之前返回的函数来传递具有封闭范围的 lambda:

void test()
{
int t = 1;
enqueue_task([&]() { do_something(t); });
}

在这种情况下,当 lambda 表达式指定的任务被安排执行时,“t”很可能会超出范围。显然,这会导致丑陋的错误。

我的解决方案是这样的语言功能:
template<class T>
void enqueue_task(T lambda)
{
static_assert(!std::is_lambda<T>::value || std::is_lambda_captured_by_value<T>::value,
"The lambda expression is executed asynchronously and therefore capturing eclosing state via reference is forbidden.");

// enqueue task for execution
}

对我来说,这将是一个干净的“非侵入性”扩展,允许中间件编写者保护他们的 API 免受滥用。当然,它不提供防弹保护,因为我仍然可以按值传递指向堆栈对象的指针,可能还有更多。无论如何,在按值传递时仍然会默默地导致未定义行为的代码本身可能已经有问题了。

有没有类似我可以做的事情已经得到支持?

对我来说,目前一个理智的解决方案似乎根本不允许在延迟执行情况下使用任何 lambda 表达式。例如,不应允许事件处理程序为 lambda 类型。说起来容易做起来难,因为这也意味着我不能使用 std::function 并且必须回到好的旧函数类型。

更好的方法是引入某种关键字,例如:
void test()
{
int t = 1;
enqueue_task(deferred () { do_something(t); });
}

这将确保,无论如何编译器都可以,传递的 lambda 函数将适合延迟执行,这意味着当它的封闭范围消失时。

我认为 C++11 在使 C++ 编程安全方面走了很长一段路。这个 lambda 的东西是少数几个你仍然用枪指着脚的地方之一。它只是一个滴答作响的定时炸弹。

最佳答案

通常补救措施是按值捕获 [=]() {...} .
当复制实际对象不可行时,通过 shared_ptr 使用它通常是有益的。 ,这可能会提供更便宜的复制,具体取决于上下文,并且还允许您共享所有权,以便调用者和延迟的 lambda 独立使用它。

C++14 应该具有移动捕获语义,这将解决在不需要共享时复制对象的性能问题。

否则,传递 by-ref 就是你想要的。就像 C++ 中的所有东西一样,不仅仅是在 lambda 表达式中,当你开始传递指针和引用时,你需要小心。

关于C++11:防止 lambda 作用域捕获错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21610245/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com