Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么文字和临时变量不是左值?_C++_C++11_Rvalue_Lvalue - Fatal编程技术网

C++ 为什么文字和临时变量不是左值?

C++ 为什么文字和临时变量不是左值?,c++,c++11,rvalue,lvalue,C++,C++11,Rvalue,Lvalue,我已经读到,左值是“具有定义存储位置的东西” 而且,文字和时间变量不是左值,但没有给出这种说法的理由 是因为文字和临时变量没有定义存储位置吗?如果是,那么如果不在内存中,它们驻留在哪里 我认为“定义的存储位置”中的“定义”有一定的意义,如果有(或没有),请告诉我 如果不在内存中,它们驻留在哪里 当然,它们驻留在内存中*,这是无法避免的。问题是,您的程序能否确定它们在内存中的确切位置。换句话说,您的程序是否允许获取问题所在的地址 在一个简单的例子a=5中,5的值或表示赋值为5的指令位于内存中的某个

我已经读到,
左值
是“具有定义存储位置的东西”

而且,文字和时间变量不是左值,但没有给出这种说法的理由

是因为文字和临时变量没有定义存储位置吗?如果是,那么如果不在内存中,它们驻留在哪里

我认为“定义的存储位置”中的“定义”有一定的意义,如果有(或没有),请告诉我

如果不在内存中,它们驻留在哪里

当然,它们驻留在内存中*,这是无法避免的。问题是,您的程序能否确定它们在内存中的确切位置。换句话说,您的程序是否允许获取问题所在的地址

在一个简单的例子
a=5
中,5的值或表示赋值为5的指令位于内存中的某个位置。但是,您不能使用5的地址,因为
int*p=&5
是非法的

请注意,字符串文字是“非左值”规则的一个例外,因为
const char*p=“hello”
生成字符串文字的地址


*然而,它不一定是数据存储器。事实上,它们甚至不可能在程序内存中表示为常量:例如,赋值
short a;a=0xFF00
可以表示为在上八位字节中分配
0xFF
,并清除内存中的下八位字节

而且,文字和时间变量不是左值,但没有给出这种说法的理由

这适用于除字符串文字外的所有临时文字和文字。这些实际上是左值(如下所述)

是因为文字和临时变量没有定义存储位置吗?如果是,那么如果不在内存中,它们驻留在哪里

对。文字
2
实际上并不存在;它只是源代码中的一个值。因为它是一个值,而不是一个对象,所以它不需要与任何内存关联。它可以硬编码到编译器创建的程序集中,也可以放在某个地方,但由于不一定要放在某个地方,所以您所能做的就是将其视为纯值,而不是对象

不过还有一个例外,那就是字符串文字。因为字符串文字是
const char[N]
的数组,所以它们实际上有存储空间。您可以获取字符串文本的地址,字符串文本可以衰减为指针,因此它是一个左值,即使它没有名称

临时值也是右值。即使它们作为对象存在,它们的存储位置也是短暂的。它们只会持续到它们所处的完整表达结束。你不允许带他们的地址,他们也没有名字。它们甚至可能不存在:例如,在

Foo a = Foo();
可以删除
Foo()
,并将代码语义转换为

Foo a(); // you can't actually do this since it declares a function with that signature.
因此,优化后的代码中甚至没有一个临时对象

为什么文字和临时变量不是左值

我有两个答案:一是因为它没有意义(1),二是因为标准上这么说(2)。让我们关注(1)

是因为文字和临时变量没有定义存储位置吗

这是一个不适合这里的简化。一种简化:文字和临时值不是左值,因为修改它们没有意义1

什么是
5++
rand()=0
的含义是什么?
标准规定,临时值和文本不是左值,因此这些示例无效。而且每个编译器开发人员都更快乐



1) 您可以定义和使用用户定义的类型,修改临时类型是有意义的。这个临时的将一直存在到完整表达式的评估。François Andrieux在调用
f(MyType{}.mutate())
f(my_int+1)
之间做了一个很好的类比。我认为简化仍然保持不变,因为
MyType{}。mutate()
可以被视为另一个临时变量,就像
MyType{}
was一样,就像
myint+1
可以被视为另一个
int
一样。这都是基于语义和观点的。真正的答案是:(2)因为标准是这样说的。

lvalue
代表定位值,表示在内存中占据某个可识别位置的对象

术语定位器值也用于:

C

C编程语言遵循类似的分类法,只是 赋值的作用不再重要:C表达式是 分类为“左值表达式”和其他(函数和 非对象值),其中“左值”表示标识 一个对象,一个“定位器值”[4]

所有不是
左值的东西都是排除在外的
右值。每个表达式都是
lavalue
rvalue

最初,C中使用了
lvalue
术语来表示可以保留在赋值运算符左侧的值。然而,随着
const
keywork,这一点发生了变化。并非所有的
左值都可以分配给。那些可以被称为
可修改的左值

而且文字和时间变量不是左值,而是 对此声明没有给出任何理由

根据文字,在某些情况下,左值可以是

  • 标量类型的文本
    rvalue
    ,因为它们的大小已知,很可能直接嵌入给定硬件体系结构上的机器命令中。
    5
    的内存位置是什么
  • 相反,奇怪的是,字符串
    int a =5;
    int b = 3;
    int c = a+b;
    
    int c = 6;
    &c = 4; //ERROR: &c is an rvalue
    
    int arr[] = {1, 2};
    int* p = &arr[0];
    *(p + 1) = 10;   // OK: p + 1 is an rvalue, but *(p + 1) is an lvalue
    
    int *p = &5;    // not allowed due to category rules
    *p = 6;         // oops, dangling pointer
    
    template<typename T> auto f(T&&t) -> T& { return t; }
    // ...
    int *p = f(5); // Allowed
    *p = 6;        // Oops, dangling pointer, no compiler error message.