我制作了一个包含静态成员的类。每次创建对象时,我都想在静态成员中添加指向该对象的指针。
头文件:
#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);
}
在main.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,这是我所期望的。
任何人都可以帮助我解释我做错了什么,或者我错过了什么。我猜想它必须与对象的范围有关,但是我似乎无法推理第一个示例为何不起作用。
编辑:我没有为该类添加析构函数,因为我认为这与该问题无关。
答案 0 :(得分:8)
对于全局对象,您有一个经典的问题-来自不同编译单元的全局对象的初始化顺序是不确定的,因此在这种情况下,似乎在创建这两个实例后初始化了向量。解决方案是具有静态局部矢量:
class A
{
public:
A(const int pin) { A::channels().push_back(this); };
static std::vector<A*> &channels()
{
static std::vector<A*> theInstance;
return theInstance;
}
}
因此您的初始化顺序问题将得到解决。
注意:如果尚不清楚此解决方案为何有效,则可以查看answer-您的问题与实现单例模式的问题有关,并且在那里有很深的解决方案。
答案 1 :(得分:1)
A a1{ 1 };
A a2{ 2 };
int main() {
std::cout << "Vector size: " << A::channels.size() << std::endl;
}
A a1 { 1 };
和A a2 { 2 };
具有全局创建的对象。其中,指针版本具有全局创建的指针,但是在堆上创建的对象不在全局空间中。这与您的其他示例相同。类A中的channel成员对于A.cpp而言是静态的,但是将在Main.cpp中全局创建对象。这意味着如果您希望计数正确更新,则必须将std::vector<A*> A::channels;
放入main.cpp而不是A.cpp