编译单元之间共享的全局常量对象



当我声明并初始化一个常量对象时。

// ConstClass.h
class ConstClass
{
};
const ConstClass g_Const;

两个cpp文件包括这个头。

// Unit1.cpp
#include "ConstClass.h"
#include "stdio.h"
void PrintInUnit1( )
{
printf( "g_Const in Unit1 is %d.rn", &g_Const );
}

// Unit2.cpp
#include "ConstClass.h"
#include "stdio.h"
void PrintInUnit2( )
{
printf( "g_Const in Unit2 is %d.rn", &g_Const );
}

当我构建解决方案时,没有链接错误,如果g_Const是一个非常基类型,你会得到什么!

PrintInUnit1()和PrintInUnit2()表明,在两个编译单元中有两个地址不同的独立"g_Const",为什么?

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

我知道如何修复它。(使用extern关键字进行声明,并在一个cpp文件中定义它。)

我想知道为什么我在这个样本中没有得到redfine链接错误。

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

命名空间范围内的const变量具有内部链接。所以他们基本上是两个不同的变量。没有重新定义。

3.5/3[基本链接]:

具有命名空间作用域(3.3.5)的名称具有内部链接,如果它是的名称

--对象、引用、函数或函数模板明确声明为静态或

--显式声明为const且两者都不是的对象或引用显式声明为extern,以前也未声明为具有external联动;或

--匿名联合的数据成员。

如果希望它具有外部链接,请使用extern


如另一个答案所述,头文件只是粘贴在cpp文件中。两个cpp文件中都包含相同的头文件,但它们是独立的翻译单元。这意味着一个变量的一个实例与另一个实例不同。换句话说,为了让编译器知道您已经在其他地方定义了变量,请使用extern关键字。这样可以确保在翻译单元之间只共享一个实例。然而,extern const Test test只是一个声明。你需要一个定义。在哪里定义它并不重要,只要它在某个cpp文件中定义过一次即可。您可以根据需要多次声明它(这对于将它放在头文件中很方便。)

例如:

常数.h

class Test
{
};
extern const Test test;

单元1.cpp

#include "Constant.h"
#include <iostream>
void print_one()
{ std::cout << &test << std::endl; }

装置2.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();
}

常量.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

因为您将变量定义放在了头文件中。包含头文件就像用文件的内容替换它一样。所以,第一个文件:

// 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.rn", &g_Const );
}

将变为(在编译前的预处理阶段之后):

// 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.rn", &g_Const );
}

第二个文件是:

// 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.rn", &g_Const );
}

正如您所看到的,每个文件都有单独的变量g_Const(这只是针对您的代码,可能根本没有像宏一样的变量,请参阅我最后一段中的解释)。

如果您想要的不是变量的定义,而是头文件中的声明,那么应该在头文件中使用extern关键字:

extern const ConstClass g_Const;

然后可以将g_Const变量的定义放在ConstClass.c


您的代码中有一些陷阱:

  • g_Const定义中没有指定常数值,除非您想要默认值(0),否则必须在定义中为其指定常数值
  • 在printf中,您获取C++的const变量的地址。这实际上迫使编译器在堆栈中创建变量。如果你不取地址,它可能能够推断出一个编译时的数字,其行为类似于C中的宏(你可以直接在使用const变量的代码中获得幻数)

相关内容

  • 没有找到相关文章

最新更新