为什么字符串文字不是prvalue

Why string literal is not prvalue

本文关键字:prvalue 文字 字符串 为什么      更新时间:2023-10-16

我一直在浏览价值类别。向我解释为什么字符串文字不是prvale

当表达式没有身份但可移动

时,我已经了解表达式的值/结果已属于prvalue类别
int i=42;char i='a'; //prvalue
string i ="notprvalue";

字面的" notprvalue"没有身份和可移动属性吗?

字符串文字无法移动。它们是基本类型的数组,因此,举动与副本无法区分。

和字符串文字具有脱离物体对象的身份,因为它们的寿命超过了本地范围(另一个原因无法从中移动)。这就是为什么您可以从函数中返回文字的const char*并仍然进行程序工作。另外,如果文字具有相同的字符串,则两个字符串文字可以指的是相同的字符数组(它们的指针可能相同)。因此," bar"answers" bar"可能指向相同的内存。

字符串文字是一种幻想。它们似乎是基本类型,例如intchar或指针。但是它们不是。

通常,它们不能直接加载到寄存器中。当然,指向他们的指针可能是。但是它们也不是指针。它们是数组,内部被用作指针,可以腐烂成指针,但数组不仅仅是这样,例如他们跟踪sizeof操作员的大小。数组不是基本类型。

c字符串的类型文字不是char const*甚至char *,而是C 中的char const[](或C中的char[])。如果不是这种情况,sizeof操作员将无法在字符串字面上正确工作:sizeof "Lorem ipsum dolor sit amet"是26而不是8。指针,对现代系统的尺寸持续:4或8个字节(取决于系统是32还是32或64位)。那不是您做sizeof(my_string_literal)时想要的。

因此,字符串文字是匿名的char的数组,但您可以通过文字本身神奇地指它们。从技术上讲,这可能不是正确的,但是我喜欢将字面本身视为一种"身份"。(当然是在哈希之后)对于存储在程序段中的实际字符数组。

您还可以创建一个可写入的char的数组,然后使用字符串字面的字符串初始化:char my_string[] = "my string literal"初始化,您实际在做的是将匿名char const[]的元素复制到新的char[]中。

字符串文字实际上是恒定的吗?在C 中。但是它们在C中没有正式实施,但是现代编译器不必尊重您修改它们的尝试,因此可以执行的行为不确定:char* my_string_pointer = "some literal"; my_string_pointer[5] = 'k';,但要执行char[] my_string_array = "some literal"; my_strig_array[5] = 'k'非常好。前者初始化A 指针。后者通过复制来初始化 array

因此,字符串文字是lvalues,即使在技术上未用作const,您也应该将其视为const

是不确定的行为。

理解所有这些的关键是,rvalues不是必不可少的基本字体类型。它们也可能是非基础的非文字临时工,例如:int answer = my_class().compute_something()用于struct my_class{ int data; int compute_someting(){ // ... compute ... } };

在此代码中,临时创建了my_class的实例,以评估其发生的表达式。通过对其创建LVALUE身份,它将扩大一生。但是,由于我们不这样做,所以这只是发生的陈述。在包含它的代码线结束时,它已经死了。因此,这是一个rvalue。现在,从实施方面,这就像一个短暂的匿名lvalue,当它获得"物有意义"时。在表达中。这就是为什么如果要初始化或将其分配给可以这样做的另一个LVALUE,则应该能够从中移动。因此,某些rvalues实际上像LVALUE一样可疑,但匿名和较短。正是这种见解导致了" xvalues"。并移动语义:完成时手动标记LVALUE作为临时性的能力,因此我们可以通过使用std::move铸造它来移动它。

顺便说一句,可以考虑到" pure rvalues"。从某种意义上说,它们不是被std::move铸造而成为RVALUE的LVALUE,而是从一开始就一直是Rvalues,即临时。字符串文字不是暂时的,因此它不是prvalue。字符串文字也不是xvalues,因为它们甚至在程序运行之前永久地生活在程序的数据段中 - 在磁盘上。

请参阅基思·汤普森(Keith Thompson)关于修改字符串文字以获取更多洞察力的答案:修改字符串文字