带参考变量的Singleton
Singleton with Reference Variable
我需要几个唯一的对象,这些对象在程序运行时总是可用的。我遵循Singleton设计模式,它建议使用方法getInstance()
来获取对象。但我更喜欢在不调用方法的情况下立即检索对象。所以我写了一个类,它提供了几个由引用类型而不是指针返回的唯一对象。
class Priority
{
public:
static Priority &High;
static Priority &Medium;
static Priority &Low;
std::string getName(void);
int getLevel(void);
private:
Priority(int level, std::string const& name);
~Priority();
Priority(Priority const&);
const Priority &operator = (Priority const&);
int level_;
std::string name_;
};
Priority &Priority::High = Priority(3, "High");
Priority &Priority::Medium = Priority(2, "Medium");
Priority &Priority::Low = Priority(1, "Low");
Priority::Priority(int level, std::string const& name)
: level_(level), name_(name)
{ }
Priority::~Priority() { }
inline std::string Priority::getName(void)
{
return name_;
}
inline int Priority::getLevel(void)
{
return level_;
}
我编写了一个使用上述类的示例程序。
int main()
{
Priority &m = Priority::High;
std::string name = m.getName();
int level = m.getLevel();
return 0;
}
程序运行良好。因此,我假设为变量分配的内存在程序停止或卸载存储类的dll文件之前,Priority &Priority::High = Priority(3, "High");
不会被擦除。我说得对吗?
问题
您展示的代码不应该编译:您不能将对非const
的引用绑定到右值。
Visual C++11.0和g++4.7.1:示例
[D:\dev\test]>cl foo.cppfoo.cppfoo.cpp(27):警告C4239:使用了非标准扩展:"initializing":从"Priority"转换为"Priority&"非常数引用只能绑定到左值foo.cpp(28):警告C4239:使用了非标准扩展:"initializing":从"Priority"转换为"Priority&"非常数引用只能绑定到左值foo.cpp(29):警告C4239:使用了非标准扩展:"initializing":从"Priority"转换为"Priority&"非常数引用只能绑定到左值[D:\dev\test]>gnuc foo.cppfoo.cpp:27:48:错误:从"Priority"类型的右值初始化"Priority&"类型的非常量引用无效foo.cpp:28:50:error:从"Priority"类型的右值初始化"Priority&"类型的非常量引用无效foo.cpp:29:47:错误:从"Priority"类型的右值初始化"Priority&"类型的非常量引用无效[D:\dev\test]>_
工具使用
对于Visual C++,请使用选项/W4
(警告级别4)来获得上面显示的警告。
您可以将此和其他“使其符合标准";环境变量CL
中的选项(与Microsoft链接器的LINK
相同,例如/entry:mainCRTStartup
作为默认链接器选项)。
[D:\dev\test]>echo%CL%/nologo/EHsc/GR/W4/FI"prolock/cppx/macro/c++11.for_msvc_11.h"[D:\dev\test]>_
C++修复该问题
您可以使用右值引用来代替左值引用,但是尽管Visual C++对此很满意,g++还是抱怨了私有析构函数。
因此,在参考思想的指导下–它的目的是什么–您可以简单地使用普通的静态数据成员。
然而,对于普通的静态数据成员,而不是Meyers的singleton,您可能会遇到静态初始化顺序失败的风险。因此,如果您绝对必须提供全局,我建议使用singleton。至于singleton的类型,使用最简单的解决方案通常是最好的,这意味着Meyers的singleton(我刚刚链接了第一个看起来合理的谷歌结果)。
这甚至不应该编译,您正在用临时对象初始化引用。然而,你根本不需要那里的参考资料;只需直接将静态成员声明为对象:
在标题中:
class Priority
{
public:
static Priority High;
static Priority Medium;
static Priority Low;
//...
};
在源文件中:
Priority Priority::High(3, "High");
Priority Priority::Medium(2, "Medium");
Priority Priority::Low(1, "Low");
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 尝试通过多个向量访问变量时,向量下标超出范围
- 试图让变量检查数组中的某些内容
- Cpp-Tuple使用带有变量的get
- XCode 警告"此处需要实例化变量'Singleton:<Foo>:_instance',但没有可用的定义
- 带参考变量的Singleton
- 作为静态字段的Singleton实例与getInstance()方法中的静态变量
- Singleton - Impl.使用静态类成员vs.静态成员变量
- C++避免全局变量和Singleton
- c++:logger类,不带全局变量或singleton,或将其传递给每个方法