Why does this variable have different values in different source files?

I have the following code:

main.cpp

#include "Test.h"

int main() {
    Create();
}

Test.h

#pragma once

#include <iostream>

#include "Function.h"

class Test {
public:
    Test();
};

extern Test* g_pTest;

inline void Create() {
    g_pTest = new Test;
    std::cout << "On Test.h: " << std::endl;
    PrintAddr();
}

Test.cpp

#include "Test.h"

Test* g_pTest = nullptr;

Test::Test() {
    std::cout << "On Test.cpp:" << std::endl;
    PrintAddr();
}

Function.h

#pragma once

void PrintAddr();

Function.cpp

#include "Function.h"
#include "Test.h"

void PrintAddr() {
    std::cout << "g_pTest address is " << g_pTest << std::endl;
}

When I run it, I get the following output:

On Test.cpp:

g_pTest address is 0000000000000000

On Test.h:

g_pTest address is 000002008A5EAE40

I thought that a extern variable was supposed to have the same value anywhere on the code, so why doesn’t it? I’ve tried to run the same code, but instead of the Test class, I just have a function:

Test.h

#pragma once

#include <iostream>

#include "Function.h"

void Test();

extern int* g_pTest;

inline void Create() {
    g_pTest = new int;
    Test();
    std::cout << "On Test.h: " << std::endl;
    PrintAddr();
}

Test.cpp

#include "Test.h"

int* g_pTest = nullptr;

void Test() {
    std::cout << "On Test.cpp:" << std::endl;
    PrintAddr();
}

And it somehow works if it is done this way, I don’t understand the logic…
What am I doing wrong here? What can I do in order to use a class and have access to the same extern variable in any code file?

>Solution :

int main() {
    Create();
}

main calls Create(), which does this:

    g_pTest = new Test;

Test gets newed first. g_pTest gets assigned after Test‘s constructor finishes and the object is constructed.

Test‘s constructor calls PrintAddr which prints the value of g_pTest because it is still nullptr:

Test* g_pTest = nullptr;

This remains the case until after Test finishes constructing.

Only after the constructor wraps up its business the pointer to the new object gets assigned to g_pTest, and then the 2nd call to printAddr (from Create) prints the value of the pointer, which is now pointing to the new object.

Leave a Reply