2013-06-11 33 views
3

我想知道什麼區別如下定義之間:String作爲指針VS陣列

// file.cpp: 
namespace n 
{ 
static char const * const str1 = "hello"; 
static char const str2[] = "hello"; 
} 

行爲我想要的,我想他們都提供:

  • 他們均指不可變的數據(因爲數據是char常量)
  • 這兩個變量都不能修改(因爲str1被定義爲* const並且因爲str2是一個不能用作l值的數組?)
  • 它們都具有內部鏈接(通過靜態)
  • 他們都有命名空間範圍
  • 如果一個指針或者字符串數據提供給不同的模塊(通過這裏沒有指定某些功能),對於那些字符串存儲會是有效的(str1,因爲它指向字符串文字,而str2是因爲該數組是在名稱空間範圍聲明的)

是否有語言保證有任何差異? 如果存在與實施相關的行爲,我該如何調查我在不同平臺上的差異?

(在這個例子中,我不感興趣,對比這些行爲具有的std :: string選項,雖然隨意談論太多,如果你認爲其他讀者會感興趣。)

+0

沒有區別。 – tay10r

+2

@TaylorFlores沒有區別?真? – 2013-06-11 18:42:34

+2

@TaylorFlores是的! – juanchopanza

回答

4

可以很容易地運行到兩個從一個事實,即一個是一個數組,另一個是所產生之間的差異一個指針。例如,sizeof將評估爲n::str1n::str2的不同(即不相關)值。此外,他們兩人都是左值(是什麼讓你覺得他們是不是?),這意味着,你可以申請&給他們,並得到完全不同的結果

&n::str1; // evaluates to a `char const *const *` value 
&n::str2; // evaluates to a `char const (*)[6]` value 

另外還要注意,第一個是直接指針進入一些不可變的實現擁有的「字符串文字存儲區」,而第二個是由「你」擁有的數組,通過從上述「字符串文字存儲區」複製數據來初始化。允許實現在整個程序中合併這些實現擁有的字符串文字。例如,你聲明瞭相同的字符串字面

char const *str_another = "hello"; 

語言保證初始化另一個指針str_another不會在n::str2

assert(str_another != n::str2); // will not fail 

指向然而,這並不能保證str_another不同於n::str1

assert(str_another != n::str1); // can fail 
+0

l值在VC++ 2012'n :: str2 = n :: str2;'''產生「錯誤C2106:'=':左操作數必須是l值」。我試圖強調的主要原因是str1或str2都不可分配。原因也很有趣,但也許是次要的。 – user2246255

+1

@ user2246255:'n :: str2 = n :: str2'是一個不好的例子,因爲它可能因爲數組類型衰減而失敗。但無論如何,任務在LHS上需要一個*可修改的*左值。如果某些東西是不可分配的,這並不意味着它不是左值。這可能意味着左值不可修改。 'n :: str2'是一個不可修改的左值。 – AnT

5

是的,有:一個仍然是一個數組,另一個是一個指針。指針和數組並不相同。

一個特定的方面可能是使用sizeof運算符 - 對於指針而言,它不會導致字符串的長度,它會在數組上(當然也包括終止的NUL字符) 。

1

&n::str1char const * const *,但&n::str2char const (*)[6]

您可以在函數重載分辨率方面獲得一些區別,但只有在其中一個重載使用引用到數組類型的情況下。

template<typename T> 
void f(T); // #1 

template<typename T, std::size_t N> 
void f(T (&)[N]); // #2 

void g() { 
    f(n::str1); // calls #1, T is char const* 
    f(n::str2); // calls #2, T is char const, N is 6. 
} 

另外,作爲@ H2CO3指出的,sizeof(n::str1)sizeof(char const*),但sizeof(n::str2)是6.