簡體   English   中英

全球外部。 字符串和字符之間的區別*

[英]Global Externs. Difference between string and char*

我有兩個問題:

  1. 我曾經有一個Constants.h包含

     const std::string PATH("/ram/") 

    而且效果很好。

    但是當我添加

     const char* BLAH = "blah"; 

    到同一文件。 鏈接期間出現重新定義錯誤。

    我知道這是因為每個編譯單元都會創建自己的常量,因此這會在鏈接期間引起問題,但是為什么它對常規的std :: strings有效而不對char * s有效?

  2. 因此,在發布第一個問題之后,我決定將所有內容都設為外部,現在有了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.

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