通过 "std::lock_guard<mutex>" 引用 return 共享对象安全吗?

Is it safe to return a shared object by reference with "std::lock_guard<mutex>"?

#include <vector>
#include <string>
#include <mutex>
#include <future>

using namespace std;

mutex g_mtx;
vector<string> g_coll;

void Cleaner()
{
    lock_guard<mutex> lock(g_mtx);
    g_coll.clear();
}

const vector<string>& Getter()
{
    lock_guard<mutex> lock(g_mtx);
    return g_coll;
}

int main()
{
    g_coll = { "hello" };
    auto fut = async([&]()
    {
        Cleaner();
    });

    auto returned_coll = Getter();
    fut.get();
}

如果Cleanerreturn g_coll;之后执行,C++标准是否保证returned_coll包含{ "hello" }

不,这不安全。

语义上,non-voidreturn类型returns的函数事件顺序如下:

  1. 计算 return 语句中的表达式。
  2. return 值是来自所述表达式的 copy-initialized。
  3. 自动局部变量按构造的相反顺序销毁。
  4. 控制 return 给调用者。

请注意 returned_coll 不是 return 值。相反,Getter() 是 return 值。 Getter() 从左值 return 对 returned_coll 的初始化发生在步骤 4 之后。

因此,当returned_collGetter()变为copy-initialized时,Getter持有的mutex已经被释放,也就是说[=10=的初始化] 可能会与 Cleaner.

中的访问竞争