make_unique 不会为创建单一实例进行编译



All,

我正在使用 C++14 并且正在制作或多或少的标准单例。我正在使用最新的Visual Studio 2017。 此代码有效:

#include <memory>
class A
{
public:
static A& getInstance()
{
if (instance == nullptr)
instance = std::unique_ptr<A>(new A());
return *instance;
}
private:
A() {}
static std::unique_ptr<A> instance;
};
std::unique_ptr<A> A::instance = nullptr;

但是,当我将单例实例的创建更改为以下内容时:

instance = std::make_unique<A>();

我收到一个编译错误,指出我正在尝试访问私有成员:

Error   C2248   'A::A': cannot access private member declared in class 'A'      
c:program files (x86)microsoft visual studio2017professionalvctoolsmsvc14.14.26428includememory   2510    

这对我来说感觉像是一个错误,因为这两种形式在功能上应该是相同的?思潮?

std::unique_ptr<>的目的是控制指向对象的生存期。您可以传递std::unique_ptr<>,但这也会转移指向对象的所有权。这个概念与单例的概念不太匹配。只有一个地方允许创建(或删除(单一实例。你真的不需要为此std::unique_ptr<>。正如评论中已经说过的,有更简单的方法。我更喜欢@Praetorian的建议:

static A& getInstance() 
{
static A instance;
return instance;
}

不能使用std::make_unique<>()实例化类的原因是构造函数是私有的。要访问它,您需要访问功能是friend.看看如何使std::make_unique我班的朋友。另一种解决方案是提供一个需要私有类型作为参数的公共构造函数,如本解决方案中所述。

instance = std::make_unique<A>();

这将在函数make_unique中创建A。 但是您要呼叫的 ctor 是私人的。

private:
struct ctor_permission_t{
explicit ctor_permission_t(int){};
};
public:
explicit A(ctor_permission_t):A(){}
};

然后

instance = std::make_unique<A>(ctor_permission_t{0});

ctor_permission_t充当令牌,赋予其拥有者建造A的权利。 我们把它传递给make_unique.

ctor_permission_t中的explicit intctor 使得在不命名类型的情况下无法创建它,并且只有在实例和A的朋友中才能命名它,因为它是私有的。 这使得绕过此权限令牌变得困难。

总结其他答案并修复其中的一些缺陷: 您可以使用私有构造函数创建一个私有结构,该构造函数与您的类是朋友。然后使您的类构造函数公开,但使用该私有结构的附加参数。

此外,最好使用静态函数 witch 返回引用而不是裸静态变量。

#include <memory>
class A
{
struct Private
{ 
friend A;
private:
explicit Private() = default; 
};
public:
static A * getInstance()
{
if (!instance())
instance() = std::make_unique<A>(Private());
return instance();
}
A(Private) {};
private:
static std::unique_ptr<A> & instance()
{
static std::unique_ptr<A> inst;
return inst;
}
};

或者,如果您真的不需要任何需要使用指针和堆分配的特殊配置(例如在特殊线程中初始化实例或...

class A
{
public:
static A & getInstance()
{
static A instance;
return instance;
}
private:
A() = default;
};

相关内容

  • 没有找到相关文章

最新更新