C++ 字符串作为指针与数组

C++ 字符串作为指针与数组,c++,arrays,string,pointers,constants,C++,Arrays,String,Pointers,Constants,我想知道以下定义之间有什么区别: // file.cpp: namespace n { static char const * const str1 = "hello"; static char const str2[] = "hello"; } 我想要的行为,我认为它们都提供: 它们都引用不可变数据(因为数据是char consts) 这两个变量都不能修改(因为str1被定义为*const,而str2是一个数组,不能用作l值?) 它们都有内部连接(通过静态) 它们都有命名空间作用域 如果指

我想知道以下定义之间有什么区别:

// file.cpp:
namespace n
{
static char const * const str1 = "hello";
static char const str2[] = "hello";
}
我想要的行为,我认为它们都提供:

  • 它们都引用不可变数据(因为数据是char consts)
  • 这两个变量都不能修改(因为str1被定义为*const,而str2是一个数组,不能用作l值?)
  • 它们都有内部连接(通过静态)
  • 它们都有命名空间作用域
  • 如果指向任一字符串数据的指针可供不同模块使用(通过此处未指定的函数),则这些字符串的内存将有效(str1因为它指向字符串文字,str2因为数组在命名空间范围内声明)
语言是否保证存在任何差异? 如果存在依赖于实现的行为,我如何调查不同平台上的差异


(在本例中,我不想将这些行为与std::string选项进行对比,不过如果您认为其他读者会感兴趣,也可以随意讨论。)

是的,有:一个仍然是数组,另一个是指针。指针和数组是不同的


一个具体的方面可能是使用
sizeof
运算符-对于指针,它不会在数组上产生字符串的长度(当然也会计算终止的NUL字符)。

字符常量*常量*
,但
&n::str2
字符常量(*)[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.
}
模板
无效f(T);//#1.
模板
无效f(T(&)[N]);//#2.
void g(){
f(n::str1);//调用#1,T是字符常量*
f(n::str2);//调用#2,T是字符常量,n是6。
}

另外,正如@H2CO3所指出的,
sizeof(n::str1)
sizeof(char const*)
,但是
sizeof(n::str2)
是6。

你很容易发现两者之间的差异,因为一个是数组,另一个是指针。例如,
sizeof
将为
n::str1
n::str2
计算不同(即不相关)的值。而且,它们都是左值(是什么让你认为它们不是?),这意味着你可以对它们应用
&
,得到完全不同的结果

&n::str1; // evaluates to a `char const *const *` value
&n::str2; // evaluates to a `char const (*)[6]` value
还请注意,第一个是指向某个不可变实现的“字符串文字存储区域”的直接指针,而第二个是“您”拥有的数组,它是通过从前面提到的“字符串文字存储区域”复制数据来初始化的。允许实现在整个程序中合并这些实现拥有的字符串文本。例如,您声明了另一个用相同字符串文字初始化的指针

char const *str_another = "hello";
该语言保证
stru\u-other
不会指向
n::str2

assert(str_another != n::str2); // will not fail
但它不能保证另一个str与str1不同

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

没有区别。@TaylorFlores没有区别?真的吗?@TaylorFlores是的,有!哦对不起,也许我应该问这个question@TaylorFlores请阅读我的答案……l值出现在VC++2012中'n::str2=n::str2;'生成了“错误C2106:'=':左操作数必须是l值”。我想强调的主要一点是,str1或str2都不是可分配的。原因也很有趣,但可能是次要的。@user2246255:
n::str2=n::str2
是一个坏例子,因为它可能仅仅因为数组类型衰减而失败。但无论如何,赋值要求LHS上有一个可修改的左值。如果某物不可转让,并不意味着它不是左值。这可能意味着左值是不可修改的。
n::str2
是不可修改的左值。