[英]Global Externs. Difference between string and char*
我有兩個問題:
我曾經有一個Constants.h包含
const std::string PATH("/ram/")
而且效果很好。
但是當我添加
const char* BLAH = "blah";
到同一文件。 鏈接期間出現重新定義錯誤。
我知道這是因為每個編譯單元都會創建自己的常量,因此這會在鏈接期間引起問題,但是為什么它對常規的std :: strings有效而不對char * s有效?
因此,在發布第一個問題之后,我決定將所有內容都設為外部,現在有了Constants.h和Constants.cpp。 但是后來我遇到了另一個問題。 我有另一個文件Test.cpp,其中一個常量定義為
const std::string FOO(PATH + "booyah");
這曾經用來創建“ / ram / booyah”,但現在只是“ booyah”。 PATH
已以某種方式變為空。 我猜想這與extern和在編譯時創建的常量有關。 常量PATH
在運行時可以正常運行。
這是正確的理解嗎? 有沒有一種方法可以使所有這些很好地協同工作?
提前致謝!
當某些內容為const
它將自動變為static
如內部鏈接一樣。
因此,當您擁有const std::string
它實際上是static const std::string
。
這意味着每個編譯單元都會獲得自己的字符串副本,這雖然通常不是什么大問題,但卻浪費了內存。
要解決此問題,請使extern const std::string s;
在頭文件和extern const std::string s = "..";
在源文件中。
為了避免需要源文件,您可以嘗試使用這種方法,盡管編譯時間可能更長。 它也只會分配一次字符串。
inline const std::string& GetStr()
{
static const std::string s = "..";
return s;
}
現在,為什么const char* BLAH
不能在頭文件中編譯? 這是因為BLAH不是常數。 盡管它是只讀指針,但該指針不是恆定的,可以更改為指向其他指針。
要使代碼像使用const std::string
一樣進行編譯,必須使用const char *const BLAH = "..";
。 現在,它是一個實常數,將作為static
常數編譯。 這也遭受相同的問題,即每個編譯單元都接收指針的副本。 根據編譯器的優化,它可能還會收到字符串文字的副本。 您可以使用上面的extern
方法解決此問題。
在同一編譯單元中初始化常量的順序就是它們出現的順序。 但是,未定義在編譯單元之間初始化常量的順序。 這意味着來自一個源文件的extern
文件不應依賴於來自另一個源文件的extern
文件。
您可以通過以正確的順序在同一源文件中定義所有常量,或使用函數(可能是inline
)返回字符串來解決此問題。
const
全局變量具有內部鏈接。 您的BLAH
變量不是const
,因此默認為外部鏈接。 您可以將其聲明為static
,也可以簡單地將其設置為const
:
const char * const BLAH = "blah";
如果發現用C ++拼寫類型名稱很困難,可以使用類型別名使您的生活更輕松:
using ccp = const char *;
const std::string foo = "foo";
const ccp bar = "bar";
由於頭文件可以包含在多個CPP文件中,因此會產生沖突。 您可以使用static關鍵字。
我通常這樣做:static const char * const str =“ blah”;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.