什么是使用静态变量,就像下面的代码的缺点:为什么在C++中使用静态命名空间/类成员变量是一个坏主意?
namespace XXX
{
static int i;
class YYY
{
static m_i;
};
}
只有在使用的.cpp静态变量(因此他们是不可见的其他代码)文件就OK了?
什么是使用静态变量,就像下面的代码的缺点:为什么在C++中使用静态命名空间/类成员变量是一个坏主意?
namespace XXX
{
static int i;
class YYY
{
static m_i;
};
}
只有在使用的.cpp静态变量(因此他们是不可见的其他代码)文件就OK了?
C++允许的各种事物代表软件设计中的选择和妥协。对于其中的任何一点来说,没有什么内在的,绝对的邪恶(除了斯特劳斯特罗普教授认为破坏的设施可能的掷标准规范; -P)。
这个特定的代码在特定情况下是否是一个好选择取决于很多因素。例如:
static
:
总之暴露的符号表,如果你认识到,命名空间和静态只是减少标识的冲突,他们已经得到了全局变量相关联的所有其他优点/缺点。 ...
对于一个它不是线程安全的。你可能想要考虑带有某种锁定的单例模式来保护它。
这完全取决于你需要做什么。对使用静态技术没有普遍的反感。请注意,静态本质上是单例模式,所以关于单例的所有优点/缺点都适用。
就线程而言,您必须注意,因为同一个实例可能同时被多个线程访问。如果你只需要读取数据,那么你不应该有任何问题。如果您需要修改数据,则必须担心同步。
对于代码复用和测试,singeltons通常会造成问题。例如,您不能在测试中重新创建对象,或者并行地运行多个对象。一般情况下,当我使用单例/静态时,我试着确保所有测试,并行执行等的整个生命周期的一个实例完全可以。
隐形静,你打电话给他们(只有到编译单元)是一个很好的想法。这有助于保持线程之间的同步并正确管理它们。如果他们具有全局可见性,那么他们可以在任何时候修改(私有变量不能,所以他们也是好的)。
另请注意,原子变量可以安全地从各个线程读取/写入。对于简单的计数器,这通常是一个好的解决方案:使用原子增量在C++ 0x中,你可以使用“原子”,以前使用你的操作系统/编译器功能。与单例模式一样,您可以轻松设计每个函数被同步的类,因此单例用户不必担心它。也就是说,即使在写作时,静态本身也不是线程安全的。
您必须注意的一个缺点是所谓的“静态初始化顺序失败”。下面是一个例子:
// foo.cpp
class foo {
public:
static bar m_bar;
};
bar foo::m_bar;
// baz.cpp
class baz {
public:
baz() {
/* some code */
foo::m_bar.someMethod();
}
};
baz g_baz; //TROUBLE!!
C++标准不保证关于哪个将首先被初始化的m_bar
和g_baz
。如果幸运的话,m_bar
会首先被初始化,g_baz
将会顺利建造。如果不是,你的程序可能会出现段错误,或者更糟。
与返回的第一次使用时构建的静态指针的方法更换m_bar
规避这个问题(注:它仍然不是线程安全的):
class foo {
public:
static bar &getBar() { if(!m_barinst) m_barinst = new bar; return *m_barinst; }
private:
static bar *m_barinst;
};
bar *foo::m_barinst = NULL;
+1“这完全取决于你需要做什么“ – 2011-04-28 07:21:54
”如果您只需要读取数据,那么您不应该有任何问题“......一般来说,当另一个线程更新数据时,您无法安全地读取数据。无论程序员是否总是认为每个“一个/另一个线程”都是他们的所有权意义上的“你”所暗示的是可疑的。即使对于'int',如果你不使用某些东西来同步缓存,你可能会错过更新。 – 2011-04-28 07:24:19
@Tony,我说**只需**需要**读取**。当然,你不能在没有同步的情况下写信给它。但那是我在......之后的句子中所说的? – 2011-04-28 07:45:12