make_unique 无法编译以创建单例实例
make_unique doesn't compile for creating a singleton instance
全部,
我正在使用 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 studio17\professional\vc\tools\msvc.14.26428\include\memory 2510
这对我来说就像一个错误,因为这两种形式在功能上应该是相同的?想法?
std::unique_ptr<>
的目的是控制指向的对象的生命周期。您可以传递一个 std::unique_ptr<>
,但这也会转移所指向对象的所有权。这个概念和单例的概念不太吻合。只有一个地方允许创建(或删除)单例。你真的不需要 std::unique_ptr<>
。正如评论中已经说过的,有更简单的方法。我更喜欢@Praetorian 的建议:
static A& getInstance()
{
static A instance;
return instance;
}
你不能使用std::make_unique<>()
实例化你的class的原因是构造函数是私有的。要访问它,您需要访问函数是 friend
。看看 for that. Another solution is to provide a public constructor requiring a private type as argument, as described int .
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 int
构造函数无法在不命名类型的情况下创建它,并且只有在 A
的实例和朋友中才能命名它,因为它是私有的。这使得绕过此权限令牌变得困难。
总结其他答案并修复其中的一些缺陷:
您可以使用私有构造函数创建一个私有结构,它是您 class 的朋友。然后使您的 class 构造函数 public 但带有该私有结构的附加参数。
另外最好使用静态函数 return 引用而不是裸静态变量。
#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;
};
全部,
我正在使用 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 studio17\professional\vc\tools\msvc.14.26428\include\memory 2510
这对我来说就像一个错误,因为这两种形式在功能上应该是相同的?想法?
std::unique_ptr<>
的目的是控制指向的对象的生命周期。您可以传递一个 std::unique_ptr<>
,但这也会转移所指向对象的所有权。这个概念和单例的概念不太吻合。只有一个地方允许创建(或删除)单例。你真的不需要 std::unique_ptr<>
。正如评论中已经说过的,有更简单的方法。我更喜欢@Praetorian 的建议:
static A& getInstance()
{
static A instance;
return instance;
}
你不能使用std::make_unique<>()
实例化你的class的原因是构造函数是私有的。要访问它,您需要访问函数是 friend
。看看
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 int
构造函数无法在不命名类型的情况下创建它,并且只有在 A
的实例和朋友中才能命名它,因为它是私有的。这使得绕过此权限令牌变得困难。
总结其他答案并修复其中的一些缺陷: 您可以使用私有构造函数创建一个私有结构,它是您 class 的朋友。然后使您的 class 构造函数 public 但带有该私有结构的附加参数。
另外最好使用静态函数 return 引用而不是裸静态变量。
#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;
};