简体   繁体   中英

Global const object shared between compilation units

When I declared and initialized a const object.

// ConstClass.h
class ConstClass
{
};

const ConstClass g_Const;

And two cpp files include this header.

// Unit1.cpp
#include "ConstClass.h"
#include "stdio.h"

void PrintInUnit1( )
{
    printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}

and

// Unit2.cpp
#include "ConstClass.h"
#include "stdio.h"

void PrintInUnit2( )
{
    printf( "g_Const in Unit2 is %d.\r\n", &g_Const );
}

When i build the solution, there was no link error, what you will get If g_Const is a non-const fundamental type!

And PrintInUnit1() and PrintInUnit2() show that there are two independent "g_Const"s with different address in two compilation units, Why?

==============

I know how to fix it.(use extern keyword to declaration, and define it in one cpp file.)

I wonder to know why I did't get redfined link error in this sample.

https://stackoverflow.com/a/6173889/1508519

const variable at namespace scope has internal linkage. So they're basically two different variables. There is no redefinition.

3.5/3 [basic.link]:

A name having namespace scope (3.3.5) has internal linkage if it is the name of

— an object, reference, function or function template that is explicitly declared static or,

— an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage; or

— a data member of an anonymous union.

Use extern if you want it to have external linkage.


As stated in the other answer, header files are just pasted in cpp files. The same header file is included in both cpp files, but they are separate translation units . That means that one instance of a variable is different from the other instance. In other to let the compiler know that you have defined the variable elsewhere, use the extern keyword. This ensures only one instance is shared across translation units. However extern const Test test is just a declaration. You need a definition. It doesn't matter where you define it as long as it is defined once in some cpp file. You can declare it as many times as you want (which is convenient for placing it in a header file.)

So for example:

Constant.h

class Test
{
};

extern const Test test;

Unit1.cpp

#include "Constant.h"
#include <iostream>

void print_one()
{ std::cout << &test << std::endl; }

Unit2.cpp

#include "Constant.h"
#include <iostream>

void print_two()
{ std::cout << &test << std::endl; }

main.cpp

extern void print_one();
extern void print_two();

int main()
{
   print_one();
   print_two();
}

Constant.cpp

#include "Constant.h"
const Test test = Test();

Makefile

.PHONY: all
all:
   g++ -std=c++11 -o test Constant.cpp Unit1.cpp Unit2.cpp main.cpp

Because you put variable definition in header file. Including header file is just like replacing it with the content of the file. So, the first file:

// Unit1.cpp
#include "ConstClass.h"  // this will be replace with the content of ConstClass.h
#include "stdio.h"

void PrintInUnit1( )
{
    printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}

will become (after preprocessing phase before compiling):

// Unit1.cpp
// ConstClass.h
class ConstClass
{
};

const ConstClass g_Const;
//this line is replaced with the content of "stdio.h"

void PrintInUnit1( )
{
    printf( "g_Const in Unit1 is %d.\r\n", &g_Const );
}

And the second file will be:

// Unit2.cpp
// ConstClass.h
class ConstClass
{
};

const ConstClass g_Const;
//this line is replaced with the content of "stdio.h"

void PrintInUnit2( )
{
    printf( "g_Const in Unit2 is %d.\r\n", &g_Const );
}

As you can see, each file has separate variable g_Const (this is just for the case of your code in here, there maybe no variable at all just like macro, see explanation in my last paragraph).

If what you want is not the definition of the variable just the declaration in the header file, you should use extern keyword in the header file:

extern const ConstClass g_Const;

Then you can put the definition of g_Const variable in ConstClass.c


There is some catch in your code:

  • there is no constant value assigned in your g_Const definition, you must assign it a constant value in the definition unless you want the default value (0).
  • inside printf, you take the address of const variable of C++. This actually force the compiler to create the variable in stack. If you don't take the address it may be able to infer a compile time number behaving like macro in C (you can get the magic number directly put in the code where you use the const variable).

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