簡體   English   中英

編譯單元之間共享的全局const對象

[英]Global const object shared between compilation units

當我聲明並初始化一個const對象時。

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

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

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

當我構建解決方案時,沒有鏈接錯誤,你會得到什么如果g_Const是一個非const基本類型!

PrintInUnit1()和PrintInUnit2()表明在兩個編譯單元中有兩個獨立的“g_Const”具有不同的地址,為什么?

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

我知道如何修復它。(使用extern關鍵字進行聲明,並在一個cpp文件中定義它。)

我想知道為什么我在這個示例中沒有得到redfined鏈接錯誤。

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

命名空間范圍內的const變量具有內部鏈接。 所以它們基本上是兩個不同的變量。 沒有重新定義。

3.5 / 3 [basic.link]:

具有命名空間范圍(3.3.5)的名稱具有內部鏈接(如果它的名稱)

- 明確聲明為靜態的對象,引用,函數或函數模板,或

- 顯式聲明為const的對象或引用,既未顯式聲明為extern,也未聲明為具有外部鏈接; 要么

- 匿名聯盟的數據成員。

如果您希望它具有外部鏈接,請使用extern


如另一個答案所述,頭文件只是粘貼在cpp文件中。 兩個cpp文件中都包含相同的頭文件,但它們是單獨的轉換單元 這意味着變量的一個實例與另一個實例不同。 另一方面,讓編譯器知道您已在其他地方定義了變量,請使用extern關鍵字。 這確保了翻譯單元之間只共享一個實例。 然而, extern const Test test只是一個聲明。 你需要一個定義。 只要在某個cpp文件中定義了一次就定義它並不重要。 您可以根據需要多次聲明它(這樣可以方便地將其放在頭文件中。)

例如:

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

因為您將變量定義放在頭文件中。 包含頭文件就像用文件內容替換它一樣。 那么,第一個文件:

// 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 );
}

將成為(在編譯之前的預處理階段):

// 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 );
}

第二個文件將是:

// 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 );
}

正如您所看到的,每個文件都有單獨的變量g_Const (這只是針對您的代碼的情況,可能根本沒有像宏一樣的變量,請參閱我上一段中的解釋)。

如果你想要的不是變量的定義,而只是頭文件中的聲明,你應該在頭文件中使用extern關鍵字:

extern const ConstClass g_Const;

然后,您可以將g_Const變量的定義放在ConstClass.c


您的代碼中有一些問題:

  • g_Const定義中沒有分配常量值,除非您需要默認值(0),否則必須在定義中為其分配一個常量值。
  • 在printf中,你取C ++的const變量的地址。 這實際上迫使編譯器在堆棧中創建變量。 如果你不接受地址,它可能能夠推斷出在C中表現得像宏的編譯時間數(你可以直接將幻數放在你使​​用const變量的代碼中)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM