我使用函数静态变量,我想通过调用setter来初始化一次:
void foo() {
static Obj obj;
obj.setName("name"); // this should be called once
// use obj
}
我不希望多次调用setter,也是由于多线程问题而且我无法向Obj添加构造函数,因为我不拥有代码。这是合理且线程安全的:
void foo() {
static Obj obj = []() {
Obj o;
o.setName("name");
return o;
}();
// use obj
}
答案 0 :(得分:1)
是的,这是线程安全的。引用n3337 - [stmt.dcl]/4,强调我的:
...这样的变量在第一次控制传递时被初始化 通过宣言;这样的变量被认为是初始化的 在初始化完成后。如果初始化退出 通过抛出异常,初始化不完整,所以它 下次控制进入声明时将再次尝试。 如果 控件在变量的同时输入声明 在初始化时,并发执行应等待完成 初始化。
您从lambda的返回值执行复制初始化,但它并不重要。上面的段落不会将obj
的初始化限制为值或直接初始化。所有形式的初始化都适用。
作为旁注,如果你必须应对这种写得不好的类型,我认为你的解决方案非常惯用。它不会人为地引入新的命名函数来执行初始化。而是保持初始化代码本地化。这在我的书中是件好事。