简体   繁体   中英

Global objects and static members of class

I made a class which has a static member in it. Every time an object is created I want to add the pointer to this object in the static member.

Header file:

#include <vector>

class A
{
public: 
    A(const int pin);
    ~A();
    static std::vector<A*> channels;

private:
    int pin_number;
}

cpp file:

 #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);

 }

In the main.cpp I want to declare the object. However, when I declare and initialize as a global variable it doesn't seem to work:

A a1{ 1 };
A a2{ 2 };

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

The above mentioned code doesn't seem to work. In the constructor of the object I see the vector being filled. The output is 0 in the above case.

For the 2 code samples below, however, does seem to work.

Sample 1:

A *a1;
A *a2;

int main() {
    a1 = new A{ 1 };
    a2 = new A{ 2 };

    std::cout << "Vector size: " << A::channels.size() << std::endl;
} 

Sample 2:

int main() {
    A a1{ 1 };
    A a2{ 2 };

    std::cout << "Vector size: " << A::channels.size() << std::endl;
}

In the above 2 cases it prints 2, which is what I expected.

Can anyone help me explain what i'm doing wrong, or what I'm missing. I'm guessing it has to do something with the scope of the objects but I can't seem to reason why the first example doesn't work.

Edit: I didn't add the destructor for the class since I didn't think it is relevant for this question.

With global object you have classical problem - order of initialization of global objects from different compilation units is undefined, so in this case it seems your vector initialized after those 2 instances are created. Solution is to have static local vector:

class A
{
public: 
    A(const int pin) { A::channels().push_back(this); };

    static std::vector<A*> &channels() 
    {
        static std::vector<A*> theInstance;
        return theInstance;
    }
}

so your issue with initialization order would be resolved.

Note: if it is unclear why this solution works you can look into this answer - your problem is related to problem of implementing singleton pattern and it is deeply addressed there.

A a1{ 1 };
A a2{ 2 };

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

The A a1 { 1 }; and A a2 { 2 }; has the objects created globally. Where as the pointer version has the pointers created globally, but the objects created on the heap not in global space. This is the same for your other example. The channels member in class A is static to A.cpp, but the objects are being created in Main.cpp globally. This means if you want the count to update properly, you'll have to put std::vector<A*> A::channels; into the main.cpp and not the A.cpp

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM