类的全局对象和静态成员



我创建了一个包含静态成员的类。每次创建对象时,我都想在静态成员中添加指向该对象的指针。

头文件:

#include <vector>
class A
{
public: 
A(const int pin);
~A();
static std::vector<A*> channels;
private:
int pin_number;
}

CPP 文件:

#include "A.h"
std::vector<A*> A::channels;
A::A(const int pin) : pin_number(pin) { A::channels.push_back(this); };
A::~A() { 
std::vector<A*>::iterator ch = std::find(A::channels.begin(), A::channels.end(), this);
if (ch != A::channels.end()) {
A::channels.erase(ch);
}

总的来说.cpp我想声明对象。但是,当我声明并初始化为全局变量时,它似乎不起作用:

A a1{ 1 };
A a2{ 2 };
int main() {
std::cout << "Vector size: " << A::channels.size() << std::endl;
}

上面提到的代码似乎不起作用。在对象的构造函数中,我看到正在填充的向量。在上述情况下,输出为 0。

但是,对于下面的 2 个代码示例,似乎确实有效。

示例 1:

A *a1;
A *a2;
int main() {
a1 = new A{ 1 };
a2 = new A{ 2 };
std::cout << "Vector size: " << A::channels.size() << std::endl;
} 

示例 2:

int main() {
A a1{ 1 };
A a2{ 2 };
std::cout << "Vector size: " << A::channels.size() << std::endl;
}

在上述 2 种情况下,它打印 2,这是我所期望的。

谁能帮我解释我做错了什么,或者我错过了什么。我猜它必须与对象的范围有关,但我似乎无法解释为什么第一个示例不起作用。

编辑:我没有为类添加析构函数,因为我认为它与这个问题无关。

对于全局对象,您会遇到经典问题 - 来自不同编译单元的全局对象的初始化顺序是不确定的,因此在这种情况下,您的向量似乎在创建这两个实例后进行了初始化。解决方案是具有静态本地向量:

class A
{
public: 
A(const int pin) { A::channels().push_back(this); };
static std::vector<A*> &channels() 
{
static std::vector<A*> theInstance;
return theInstance;
}
}

因此,您的初始化顺序问题将得到解决。

注意:如果不清楚为什么这个解决方案有效,你可以看看这个答案 - 你的问题与实现单例模式的问题有关,并且在那里得到了深入的解决。

A a1{ 1 };
A a2{ 2 };
int main() {
std::cout << "Vector size: " << A::channels.size() << std::endl;
}

A a1 { 1 };A a2 { 2 };具有全局创建的对象。 其中,指针版本具有全局创建的指针,但在堆上创建的对象不在全局空间中。 您的另一个示例也是如此。 类 A 中的通道成员对 A.cpp 是静态的,但对象是在 Main .cpp全局中创建的。 这意味着如果您希望计数正确更新,则必须将std::vector<A*> A::channels;放入主.cpp而不是 A 中.cpp

最新更新