全局对象和类的静态成员

时间:2018-10-25 20:04:27

标签: c++ c++11 c++14

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

头文件:

#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,这是我所期望的。

任何人都可以帮助我解释我做错了什么,或者我错过了什么。我猜想它必须与对象的范围有关,但是我似乎无法推理第一个示例为何不起作用。

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

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