c++ - 检查在gcc 4.4.7中没有初始化whter atomic ptr(无nullptr)

标签 c++ c++11 gcc gcc4

在将单例类重构为线程安全(fallowing Herb Sutter advice how to write proper double-check locking)的过程中,我遇到了支持原子但不支持nullptr的编译器版本(带有--std = c++ 0x标志的gcc 4.4.7)问题。

当前代码

class SingletonClass {
   public:
SingletonClass* getInstance() {
    if (instance == NULL) {
        instance == new SingletonClass();
    }
    return instance;
}

   private:
SingletonClass() = default;
~SingletonClass() = default;

static SingletonClass* instance;};

我想达到的目标
#include <cstdatomic>
#include <mutex>

class SingletonClass {
   public:
SingletonClass* getInstance() {
    if (instance == NULL) {
        std::lock_guard<std::mutex> lock (m);
        if(instance == NULL){
           instance = new SingletonClass();
        }
    }
    return instance;
}

   private:
 SingletonClass() = default;
~SingletonClass() = default;

static std::atomic<SingletonClass*> instance;
static std::mutex m;
};

但这给了我一个错误,说没有运算符可以将原子ptr编译为NULL
main.cpp: In member function ‘SingletonClass* SingletonClass::getInstance()’:
main.cpp:7: error: ambiguous overload for ‘operator==’ in ‘SingletonClass::instance == 0l’
main.cpp:7: note: candidates are: operator==(void*, void*) <built-in>
main.cpp:7: note:                 operator==(SingletonClass*, SingletonClass*) <built-in>

由于我不能将实例ptr强制为NULL或不能使用nullptr来解决它,并检查其是否已初始化?

最佳答案

您可以使用将指针隐式转换为bool的方法:

SingletonClass* getInstance() {
    if (instance.load()) {
        std::lock_guard<std::mutex> lock (m);
        if(instance.load()){
           instance.store(new SingletonClass());
        }
    }
    return instance;
}

See it online

请注意,从std::atomic<SingletonClass*>SingletonClass*的隐式转换是可能的,但是在这种情况下是模棱两可的。另外,分配本身是模棱两可的,因此添加了store()调用。

但是,也许解决方案更简单-为什么您完全需要std::atomic?您已经锁定了对存储指针的访问,因此很安全:
#include <mutex>

class SingletonClass {
public:
    SingletonClass* getInstance() {
        std::lock_guard<std::mutex> lock (m);
        if (instance == NULL) {
            instance = new SingletonClass();
        }
        return instance;
    }

private:
    SingletonClass() = default;
    ~SingletonClass() = default;

    static SingletonClass* instance;
    static std::mutex m;
};
std::atomic用于无锁访问(或至少“隐藏锁”访问)。我想不出同时使用两者的理由。

这里非常需要Mutex-您想将整个功能锁定为关键部分,否则两个线程可能会创建两个单例对象,而一个则会泄漏。

关于c++ - 检查在gcc 4.4.7中没有初始化whter atomic ptr(无nullptr),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60620742/

相关文章:

c - C中的字符串反向程序

c++ - 循环终止条件错误的 cpp vector

c++ - 为什么用 std::forward 禁用模板参数推导?

c++ - 正确实现类函数数组

c++ - 怎么才能看到这个header?

xcode - 项目 header Xcode 11中的Cant访问变量或类型

c - 这个有两个主要函数的C程序是如何编译运行的呢?

c - 使用 gcc 理解共享库

c++ - 指向字符混淆的指针

c++ - C语言有前置自增和后置自增的历史原因是什么?