相关疑难解决方法(0)

C++ Singleton设计模式

最近我碰到了C++的Singleton设计模式的实现/实现.看起来像这样(我从现实生活中采用了它):

// a lot of methods are omitted here
class Singleton
{
   public:
       static Singleton* getInstance( );
       ~Singleton( );
   private:
       Singleton( );
       static Singleton* instance;
};
Run Code Online (Sandbox Code Playgroud)

从这个声明我可以推断出实例字段是在堆上启动的.这意味着存在内存分配.对我来说完全不清楚的是,什么时候内存将被解除分配?还是有漏洞和内存泄漏?好像在实施中存在问题.

我的主要问题是,如何以正确的方式实施它?

c++ singleton design-patterns

692
推荐指数
11
解决办法
65万
查看次数

C++ 11中的局部静态变量初始化是否是线程安全的?

我知道这是一个经常被问到的问题,但由于有很多变种,我想重新陈述它,并希望有一个反映当前状态的答案.就像是

Logger& g_logger() {
    static Logger lg;
    return lg;
}
Run Code Online (Sandbox Code Playgroud)

变量lg的构造函数是否保证只运行一次?

我从以前的答案中知道,在C++ 03中,这不是; 在C++ 0x草案中,这是强制执行的.但我想要一个更明确的答案

  1. 在C++ 11标准(非草稿)中,线程安全的初始化行为是否已完成?
  2. 如果以上是肯定的,那么在当前最新版本的热门编译器中,即gcc 4.7,vc 2011和clang 3.0,它们是否正确实施?

c++ thread-safety c++11

198
推荐指数
2
解决办法
6万
查看次数

单线程与多线程

在一次采访中询问了这个问题.第一部分是编写单例类:

class Singleton
{
    static Singleton *singletonInstance;
    Singleton() {}

  public:
    static Singleton* getSingletonInstance()
    {
        if(singletonInstance == null)
        {
            singletonInstance = new Singleton();
        }
        return singletonInstance;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后我被问到如何getSingletonInstance()在多线程情况下处理这个问题.我不太确定,但我修改为:

class Singleton 
{
    static Singleton *singletonInstance;
    Singleton() {}
    static mutex m_;

  public:
    static Singleton* getSingletonInstance()
    {
        m_pend();
        if(singletonInstance == null)
        {
            singletonInstance = new Singleton();
        }
        return singletonInstance;
    }

    static void releaseSingleton()
    {
        m_post();
    }
};
Run Code Online (Sandbox Code Playgroud)

然后有人告诉我,虽然需要一个互斥锁,但挂起和发布互斥锁效率不高,因为需要时间.并且有一种更好的方法来应对这种情况.

有没有人知道在多线程情况下处理单例类的更好,更有效的方法?

c++ singleton multithreading synchronization mutex

22
推荐指数
2
解决办法
2万
查看次数

我是否可以在使用C++构建静态本地时访问它?

保证在C++标准首次使用时实例化静态本地.但是,我想知道如果我在构建时访问静态本地对象会发生什么.我认为这是UB.但在以下情况下避免这种情况的最佳做法是什么?

一个问题的情况

Meyers Singleton模式在静态getInstance()方法中使用静态局部来在第一次使用时构造对象.现在,如果构造函数(直接或indireclty)getInstance()再次调用,我们将面临静态初始化尚未完成的情况.这是一个最小的例子,它说明了问题情况:

class StaticLocal {
private:
    StaticLocal() {
        // Indirectly calls getInstance()
        parseConfig();
    }
    StaticLocal(const StaticLocal&) = delete;
    StaticLocal &operator=(const StaticLocal &) = delete;

    void parseConfig() {
        int d = StaticLocal::getInstance()->getData();
    }
    int getData() {
        return 1;
    }

public:
    static StaticLocal *getInstance() {
        static StaticLocal inst_;
        return &inst_;
    }

    void doIt() {};
};

int main()
{
    StaticLocal::getInstance()->doIt();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在VS2010中,这没有问题,但VS2015死锁.

对于这种简单,减少的情况,显而易见的解决方案是直接呼叫getData(),而无需getInstance()再次呼叫.但是,在更复杂的情况下(根据我的实际情况),这种解决方案是不可行的.

尝试解决方案

如果我们改变getInstance()方法来处理像这样的静态局部指针(从而放弃Meyers Singleton模式):

static StaticLocal …
Run Code Online (Sandbox Code Playgroud)

c++ static-initialization visual-studio-2015

11
推荐指数
3
解决办法
871
查看次数

在另一个翻译单元的静态破坏阶段引用时,"魔术静态"单例崩溃

我有一个琐碎的单身课程.我的singleton.h文件看起来像这样:

class singleton
{
...
public:
    static singleton& instance();
};
Run Code Online (Sandbox Code Playgroud)

singleton.cpp看起来像这样:

...
singleton& singleton::instance()
{
    static singleton * const _instance(new singleton);
    return *_instance;
}
Run Code Online (Sandbox Code Playgroud)

在编写这个类时,我认为我依赖于线程安全的函数本地静态初始化,我理解这将在这里描述的C++标准的第6.7节中阐述.希望我明白这是如何工作的.

我正在使用2013年11月的CTP工具链运行Visual C++ .微软称2013年11月CTP支持线程安全的函数本地静态初始化,并快速浏览编译器生成的目标代码,表明它正在尝试这样做.

我的问题是,在另一个翻译单元中销毁静态存储持续时间对象需要访问singleton::instance().我预计这不会有任何困难,因为静态变量支持singleton::instance()是一个永不删除的指针.但是,singleton::instance()来自该其他对象的调用正在崩溃我的进程,堆栈跟踪如下所示:

_Init_thread_header
singleton::instance
other_translation_unit_object::~other_translation_unit_object
Run Code Online (Sandbox Code Playgroud)

其中_Init_thread_header()似乎是由编译器插入来实现线程安全的静态初始化.

所以我的问题是:上面的代码是否表明我从根本上误解了静态初始化应该如何工作(最可能的情况是,如果是这样,那就好了:),或者是否有可能出现其他问题?

c++ singleton multithreading visual-c++ c++11

7
推荐指数
1
解决办法
4548
查看次数

如何在使用Clang编译CRTP Singleton时修复声称缺少"显式实例化声明"?

我们正在使用奇怪的重复模板模式来实现单例.但是,在最近的Clang版本中,我们得到了一个-Wundefined-var-template警告.建议的修复是添加"显式实例化声明".

我试图这样做,但后来我在编译单元中获得了"实例化后显式特化"的错误,其中单例模板类成员变量的定义是.

解决此警告突出显示的问题的适当构造是什么?


简化细节(已删除大部分逻辑,以制作MCVE):

SingletonBase.hh:

template < class T > class SingletonBase {
public:
  static T * get_instance() {
    if ( ! instance_ ) {
      instance_ = T::create_singleton_instance();
    }
    return instance_;
  }
private:
  static T * instance_;
};
Run Code Online (Sandbox Code Playgroud)

Singleton.hh:

#include "SingletonBase.hh"

class Singleton : public SingletonBase< Singleton > {
  friend class SingletonBase< Singleton >;
public:
  int do_stuff(int v) { return v+2; }
private:
  static Singleton * create_singleton_instance() {
    return new Singleton;
  }
};
Run Code Online (Sandbox Code Playgroud)

Singleton.cc:

#include "Singleton.hh"
template …
Run Code Online (Sandbox Code Playgroud)

c++ singleton crtp c++11 clang++

6
推荐指数
2
解决办法
3629
查看次数

如何在C++11代码中实现单例模式和工厂模式

我正在尝试同时实现单例模式和工厂模式。在我看来,每种工厂只能有一个工厂,它们基于一个抽象类,并使用工厂来生产相应的shape对象。

但我收到一个错误:

错误LNK2001:无法解析的外部符号“私有:静态类TriangleFactory * TriangleFactory ::实例”(?instance@TriangleFactory@@0PAV1@A)

我不知道为什么会发生这种情况。你能告诉我如何解决它吗?代码如下。

#include<type_traits>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<memory>
#include<time.h>
using namespace std;

class Shape
{
public:
    virtual void display();
protected:
    int x, y;
};

class MyTriangle:public Shape
{
public:
    MyTriangle(int _x, int _y)
    {
        x = _x;
        y = _y;
    }
    MyTriangle()
    {
        x = rand() % 200;
        y = rand() % 200;
    }
    void display()
    {
        printf("%d %d\n",x,y);
    }
};

class SuperFactory
{
public:
    virtual Shape* Execute() = 0;
};

class TriangleFactory :public …
Run Code Online (Sandbox Code Playgroud)

c++ singleton design-patterns

1
推荐指数
1
解决办法
6082
查看次数