【问题标题】:Calling setter once on function static variable在函数静态变量上调用一次 setter
【发布时间】:2017-12-07 13:46:38
【问题描述】:

我正在使用一个函数静态变量,我想通过调用 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
}

【问题讨论】:

  • 为什么是所有东西的二传手?为什么它不能有一个合适的c'tor?
  • 为什么不使用构造函数:static Obj obj("name");
  • 我忘了说,那不是我的代码,我不拥有 Obj。我将编辑问题
  • 可能会添加第二个类,用于初始化 Obj,例如 static ObjSet objset(obj, "name"); ObjSet 将初始化 obj。我想这应该是安全的
  • 但是如果 obj 在其名称设置之前可能被其他线程使用,那么您可能会遇到问题

标签: c++ multithreading c++11 static


【解决方案1】:

是的,它是线程安全的。引用 n3337 - [stmt.dcl]/4,强调我的:

...这样的变量在第一次控制通过时被初始化 通过其声明;这样的变量被认为是初始化的 在其初始化完成后。如果初始化退出 通过抛出异常,初始化不完整,所以它 下次控制进入声明时将再次尝试。 如果 控制同时进入声明,而变量是 正在初始化,并发执行将等待完成 初始化。

您从 lambda 的返回值执行复制初始化,但这并不重要。上面的段落没有将obj 的初始化限制为值或直接初始化。所有形式的初始化都适用。

顺便说一句,如果您必须应对这种写得不好的类型,我认为您的解决方案非常地道。它没有人为地引入一个新的命名函数来执行初始化。相反,它使初始化代码保持本地化。这在我的书中是一件好事。

【讨论】:

    猜你喜欢
    • 2015-11-25
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    相关资源
    最近更新 更多