c++ - clang - shared_ptr 无法运行其删除程序

标签 c++ c++11 lambda clang shared-ptr

此代码打印 0 (没有优化)或 666 (打开优化)当使用 clang++ -std=c++11 构建时( -O3 产生 666 ,这是我所期望的)。当通过通用引用传递 lambda 时,问题就消失了。

仅供引用,GCC 打印 666在我测试过的所有版本上。

是编译器错误还是代码不正确?

#include <memory>
#include <iostream>

template <typename T>
std::shared_ptr<void> onScopeExit(T f)
{
    return std::shared_ptr<void>((void*)1, [&](void *) {
        f();
    });
}

struct A {
  void f() {
    auto scopeGuard = onScopeExit([&]() { i = 666; }); //  [1]
    // ... (some work)
  } // (lambda [1] being ? called on scope exit)

  int i = 0;
};

A a;

int main() {
  a.f();
  std::cout << a.i << std::endl;
}

有问题的编译器是:

Apple LLVM version 9.1.0 (clang-902.0.39.2)
Target: x86_64-apple-darwin17.7.0

最佳答案

您的代码有未定义的行为。您通过 onScopeExit 中的引用捕获 f 但是一旦您从函数返回 shared_ptr 删除器现在持有对 f 的悬空引用,因为 f 超出了范围。你需要做的是按值捕获f,然后你就不会有悬空引用

template <typename T>
std::shared_ptr<void> onScopeExit(T f)
{
    return std::shared_ptr<void>((void*)1, [=](void *) {
        f();
    });
}

struct A {
  void f() {
    auto scopeGuard = onScopeExit([&]() { i = 666; }); //  [1]
    // ... (some work)
  } // (lambda [1] being ? called on scope exit)

  int i = 0;
};

A a;

int main() {
  a.f();
  std::cout << a.i << std::endl;
}

关于c++ - clang - shared_ptr 无法运行其删除程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52668037/

相关文章:

c++ - operator[] for std::map 什么情况下可以返回0?

java - 如何使用 Java lambda 将 List<Foo> 收集到 Map<Bar, List<Baz>>?

c++11 - 尝试使用 lambda 函数作为 condition_variable 等待方法的谓词

java - 如果我来自 PHP/Java,在学习 C++ 时会遇到什么问题?

c++ - C++ Win32API WM_KEYDOWN和按钮

c++ - FFmpeg 中是否有源文件的字节偏移量?

c++ - 如何将类中的函数放入线程中? (使用 Boost 的 C++)

c++ - 为什么概念会使 C++ 编译速度变慢?

c++ - 将 braced-init-list 分配给数组是否正确?

java - Java 8 实例方法引用是否等同于 lambda 调用?就我而言,它不是