C++ 在.cpp上保存数据,在.h上保存函数

C++ 在.cpp上保存数据,在.h上保存函数,c++,struct,C++,Struct,我的问题更像是一个疑问 几天前,我开始用一种我不太习惯的方式组织我的代码,但我非常喜欢它,问题是我不知道它是好是坏,我是说它可以工作,但我想知道代码是否会变大,最终会成为问题。这是我如何使用代码的: .h文件 void init(); void someFunction1(); .cpp文件 struct myData { int someVar = 0; int someVar1 = 21; } myData* mydata = nullptr; void init()

我的问题更像是一个疑问

几天前,我开始用一种我不太习惯的方式组织我的代码,但我非常喜欢它,问题是我不知道它是好是坏,我是说它可以工作,但我想知道代码是否会变大,最终会成为问题。这是我如何使用代码的:

.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”指针将仅在这个特定的cpp文件上可用

那是假的
mydata
将是一个全局变量。如果在另一个.cpp中有另一个
mydata
全局变量,它们可能会发生冲突(或者至少会违反一个定义规则)

为mydata使用未命名的命名空间:

namespace {
    myData* mydata = nullptr;
}
这样,
mydata
就不会被其他翻译单元访问

但是:不建议使用全局变量。不要使用它们。他们几乎总是有其他选择

<> P>有一个技术原因,它只与C++有关:

设计决策的背后是:

  • 或者,如果您喜欢观看视频:

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\u实例
是一个对象,而不是指针,这避免了必须使用
new
来分配内存,这意味着您不必担心调用
delete
以后再次释放内存
mydata()
将在第一次调用时在堆栈上创建一个
mydata
对象,由于该对象是静态的,它将在以后每次调用
mydata()
时保持不变,并且每次都会返回相同的对象(静态局部变量只初始化一次。)请注意
mydata()的返回类型
是一个引用(用
&
表示),这意味着当您返回对象时,将返回对该对象的引用,而不是副本。这使您可以直接访问函数外部的
mydata\u实例
对象

现在,尽管上面的方法可以工作,但最好去掉
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文件上可用,“不,那是错误的。如果您在那里放置一个
static
,则为真。还有C++使用一个带有私有数据和公共成员函数的类。是的,这将是一个问题。不要创建返回空洞的函数,不带参数,不要在文件范围内创建变量。请不要在C++问题上使用C标记,它们不一样。你到底在做什么?你用这种代码干什么?当函数听起来很像方法时,为什么不使用适当的类呢?我的意思是,我希望这是一个在实际代码中看起来不同的示例,没有任何名称空间之外的像init这样的泛型名称,也没有在cpp之外甚至没有提到的全局变量。@khofez如果您在另一个
.cpp
文件中放置
extern myData*myData声明,是的。为什么不推荐全局变量?你能举个简单的例子吗?谢谢你的回答!非常感谢你的解释。哦,关于init方法,这只是一个例子,我通常不会这样做,它只是表达我所说的,但再次感谢你