我的问题更像是一个疑问。
几天前我开始以一种我不习惯的方式组织我的代码,但我很喜欢它,问题是我不知道它是坏还是好,我的意思是它的工作,但我想知道是否代码越来越大,最终会出现问题。这就是我如何处理我的代码:
.h文件
void init();
void someFunction1();
.cpp文件
struct myData
{
int someVar = 0;
int someVar1 = 21;
}
myData* mydata = nullptr;
void init()
{
mydata = new myData();
mydata->someVar = 1;
}
void someFunction1()
{
mydata->someVar = mydata->someVar1;
}
我知道" mydata"指针将只在这个特定的cpp文件上可用,并且当我包含de .h文件时,函数是我唯一可以调用的函数,但这基本上就是我想要的和它我正在做的事情,就是任何问题都在那?我的意思是,将来会像这样使用它来获取错误或任何奇怪的内容吗?
答案 0 :(得分:1)
我知道" mydata"指针将在此特定cpp文件上可用
那是假的。 mydata
将是一个全局变量。如果在另一个.cpp中有另一个mydata
全局变量,它们可能会发生冲突(或者至少它们会违反一个定义规则)。
为mydata使用未命名的命名空间:
namespace {
myData* mydata = nullptr;
}
这样,其他翻译单元无法访问mydata
。
但是:不建议使用全局变量。不要使用它们。他们几乎总是有其他选择。
有一个技术原因,仅与C ++相关:static initialization order fiasco
背后有设计决策:
答案 1 :(得分:1)
mydata
也可在其他翻译单元中使用。如果在另一个源中使用相同名称的另一个全局变量,则会产生问题。这将导致标识符冲突。
为了确保不会发生这种情况,您可以将mydata
设为静态变量:
static myData* mydata = nullptr;
或者将mydata
放在未命名的命名空间中:
namespace {
myData* mydata = nullptr;
}
在这种情况下,myData
不一定是静态的。
第二个选项现在通常在C ++中是首选,但第一个选项将完成相同的结果,并且没有任何内在错误。
请注意,全局范围内的变量存在一些与初始化相关的问题。例如,如果将全局变量初始化为在其他位置定义的另一个全局变量的值,则无法知道哪个变量将首先被初始化,因此您的变量可能会使用垃圾数据进行初始化。但是,在这种情况下,您只需将其初始化为nullptr
,这样就可以了。但是,仍然避免全局变量是一个好习惯,因为这是一种更好的方法。您可以将变量包装到静态函数中,然后返回在其中定义的静态变量:
static myData& mydata()
{
static myData mydata_instance;
return mydata_instance;
}
void init()
{
mydata().someVar = 1;
}
void someFunction1()
{
mydata().someVar = mydata().someVar1;
}
另外,请注意没有使用指针。 mydata_instance
是一个对象,而不是一个指针,这可以避免使用new
分配内存,这意味着您不必担心调用delete
以后再释放记忆了。 mydata()
会在第一次调用时在堆栈上创建一个myData
对象,并且由于该对象是静态的,因此它将在以后每次调用mydata()
时保持不变每次都会返回对象(静态局部变量只初始化一次。)请注意,mydata()
的返回类型是引用(用&
表示),这意味着当您返回对象时,引用返回该对象而不是副本。这使您可以直接访问函数外部的mydata_instance
对象。
现在,即使上面的内容有效,但摆脱init()
函数并重新设计myData
结构可能不需要它也是一个好主意。在这种情况下,只需在结构本身中将someVar
成员设置为1即可。没有理由在结构内部将其初始化为0,然后必须调用init()
将其设置为1.总体而言:
struct myData
{
int someVar = 1;
int someVar1 = 21;
}
static myData& mydata()
{
static myData mydata_instance;
return mydata_instance;
}
void someFunction1()
{
mydata().someVar = mydata().someVar1;
}