将数据保存在.cpp上,并在 .h 上运行
Holding data on .cpp and function on .h
我的问题更像是一个疑问。
几天前,我开始以一种我不太习惯的方式组织我的代码,但我非常喜欢它,问题是我不知道它是坏的还是好的,我的意思是它的工作,但我想知道如果代码变大它最终会成为问题。这是我使用代码的方式:
.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 文件时,函数是我唯一可以调用的东西,但这基本上是我想要的,它正在做的事情,这有什么问题吗?我的意思是,将来像这样使用它时会遇到错误或任何奇怪的事情吗?
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;
}
我知道"mydata"指针将只在这个特定的 cpp 文件上可用
这是错误的。mydata
将是一个全局变量。如果在另一个.cpp中有另一个mydata
全局变量,它们可能会发生冲突(或者至少它们会违反一个定义规则(。
对 mydata 使用未命名的命名空间:
namespace {
myData* mydata = nullptr;
}
这样,其他翻译单元将无法访问mydata
。
但是:不建议使用全局变量。不要使用它们。他们几乎总是有其他选择。
有一个技术原因,仅与C++有关:静态初始化订单惨败
背后还有设计决策:
- 为什么全球国家如此邪恶?
- 为什么静态变量被认为是邪恶的?
- 或者,如果您更喜欢观看视频:清洁代码会谈 - "全球状态和单例">
- 如何在运行时在对象数组中动态追加新对象C++并打印它们
- 使用 (cin) 用户输入将其粘贴到 std::system 中,并在另一个终端中运行带有输入的命令
- 生成线程并在运行时执行其他操作,只要它处于活动状态
- 我的fahrenheit-celcius程序会忽略我的if-else语句,并在每次运行该程序时将值更改为0
- 当我在支持 avx2 的机器上编译并在另一台仅支持 avx 的机器上运行二进制文件时会发生什么?
- 将数据保存在.cpp上,并在 .h 上运行
- 分离线程然后让它超出范围(并使其仍在运行)是否安全?
- 阻止进程在从服务启动时启动,并在某些进程关闭后继续运行服务。
- 在RHEL 7上编译MySqlClient,并在RHEL 6上运行(Linux上的G )
- NVCC编译了特征库,并在运行时失败的结构中的MatrixxD大小
- 在运行libtorch的模型时获得的结果是不正确的,该模型经过训练并从Pytorch出口
- 是否可以访问C++标头/库并在 python 控制台中运行C++脚本?
- 使用命令行参数从TXT文件中提取并在C 中运行特定类
- 嵌入批处理脚本文件并在C 控制台项目中运行
- Travis和Coverity扫描 - 一切都在建立,但掩护似乎并没有运行
- 如何将任何 *.jpg图像嵌入Win32可执行文件中并在运行时使用它
- 插入[n X n]矩阵类型的数据,并在运行时对其进行访问.将std::映射工作
- 实例化函数的多个模板并在运行时选择的通用解决方案
- 仅使用 DLL *.h 头文件构建(compile.link)应用程序代码,并在运行时加载 DLL 实现(显式链接)
- C++ 将数组大小分配为变量,并在运行时为变量赋值