C++ 错误 C2106:“=”:左操作数必须是左值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17930948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
error C2106: '=' : left operand must be l-value
提问by KQball
Looking at the other questions regarding error C2106, I am still lost as to what the issue is with my code. While compiling I get the following errors:
查看有关错误 C2106 的其他问题,我仍然不知道我的代码有什么问题。编译时出现以下错误:
c:\driver.cpp(99): error C2106: '=' : left operand must be l-value
c:\driver.cpp(169): error C2106: '=' : left operand must be l-value
c:\driver.cpp(99): 错误 C2106: '=' : 左操作数必须是左值
c:\driver.cpp(169): 错误 C2106: '=' : 左操作数必须是左值
The line of code is as follows:
代码行如下:
payroll.at(i) = NULL; //Line 99
payroll.at(count++) = ePtr; //Line 169
I am failing to understand why this error is being thrown. In this project I have changed my driver.cpp from an array of employee object pointers to a custom Vector template that I made. I declare the Vector as follows...
我不明白为什么会抛出这个错误。在这个项目中,我将 driver.cpp 从一组员工对象指针更改为我制作的自定义 Vector 模板。我声明向量如下...
//Declare an Vector to hold employee object pointers
MyVector <employee*> payroll;
Any help is appreciated...
任何帮助表示赞赏...
回答by Mohamad Ali Baydoun
This error is being thrown for the same reason you can't do something like this:
抛出此错误的原因与您不能执行以下操作的原因相同:
36 = 3;
Your version of Vector::at
should be returning a reference rather than a value.
Lvalues are called Lvalues because they can appear on the left of an assignment. Rvalues cannot appear on the left side, which is why we call them rvalues. You can't assign 3
to 36
because 36
is not an lvalue, it is an rvalue, a temporary. It doesn't have a memory address. For the same reason, you cannot assign NULL
to payroll.at(i)
.
您的版本Vector::at
应该返回一个引用而不是一个值。
左值之所以称为左值,是因为它们可以出现在赋值的左侧。右值不能出现在左侧,这就是我们称它们为右值的原因。你不能分配3
给36
因为36
不是左值,它是一个右值,一个临时的。它没有内存地址。出于同样的原因,您不能分配NULL
给payroll.at(i)
.
Your definition:
你的定义:
template <class V> V MyVector<V>::at(int n)
What it should be:
它应该是什么:
template<typename V> V& MyVector::at(std::size_t n)
template<typename V> const V& MyVector::at(std::size_t n) const
回答by celtschk
The message says that you try to assign to an expression which is not an lvalue. For built-in types, you can only assign to lvalues (that's where the name comes from: lvalue = value that can be on the lefthand side of the assignment operator, while rvalue = value that must be on the righthand side of the assignment operator).
该消息表示您尝试分配给不是左值的表达式。对于内置类型,您只能分配给左值(这就是名称的来源:左值 = 可以位于赋值运算符左侧的值,而 rvalue = 必须位于赋值运算符右侧的值)赋值运算符)。
So what is an lvalue or an rvalue? Consider the following code:
那么什么是左值或右值?考虑以下代码:
int a;
a = 3;
In this assignment a
is an lvalue (if it weren't, the compiler would complain). That is, the expression a
refers to an object which can be modified. On the other hand, 3
is an rvalue, that is, basically a value. Of course you cannot assign to 3
; the compiler would complain about the statement 3=a;
with exactly the same message you got in your code.
在这个赋值中a
是一个左值(如果不是,编译器会抱怨)。也就是说,表达式a
指的是一个可以修改的对象。另一方面,3
是一个右值,即基本上是一个值。当然你不能分配给3
; 编译器会抱怨该语句3=a;
的消息与您在代码中得到的消息完全相同。
So as a first approximation,an lvalue designates an object, while an rvalue designates a value. Note that this is also true for assignment of the form
因此,作为第一个近似值,左值指定一个对象,而右值指定一个值。请注意,这也适用于表单的分配
a = b;
where b
also is a variable. What happens here is the so-called lvalue to rvalue conversion: What is assigned is not the object b
, but its current value.
其中b
也是一个变量。这里发生的是所谓的左值到右值的转换:分配的不是对象b
,而是它的当前值。
Now consider the following case:
现在考虑以下情况:
int f();
f() = 3;
Here you might argue that the function f
does return an object (if you use some user-defined type, you even can see its construction/destruction). But the compiler still complains with the message you got. Why?
在这里您可能会争辩说该函数f
确实返回了一个对象(如果您使用某些用户定义的类型,您甚至可以看到它的构造/销毁)。但是编译器仍然会抱怨您收到的消息。为什么?
Well, even if you consider f
to return an object, it is a temporaryobject which will go away immediately. So it does not make much sense to assign a value because you cannot do anything with it anyway afterwards.
好吧,即使您考虑f
返回一个对象,它也是一个会立即消失的临时对象。所以分配一个值没有多大意义,因为之后无论如何你都不能对它做任何事情。
Therefore here's the second rule:
因此,这是第二条规则:
Whenever there's an expression which produces a temporary object, C++ defines that expression as rvalue.
每当有一个生成临时对象的表达式时,C++ 都会将该表达式定义为右值。
And now we come to the definition of MyVector::at()
which you did not show, but which, according to the error message, probably looks similar to this:
现在我们来看看MyVector::at()
你没有显示的定义,但根据错误消息,它可能看起来类似于:
template<typename T>
T MyVector<T>::at(int i)
{
return data[i];
}
This has essentially the same form as f
above, as it also returns a T
(an employee*
in your case). This is why the compiler complains.
这与f
上面的形式基本相同,因为它也返回一个T
(employee*
在你的情况下)。这就是编译器抱怨的原因。
And that complaint is helpful: Even if the compiler wouldn't complain, the code would not dio what you almost certainly intended. The return
statement returns a copyof the object data[i]
. Thus if the statement payment.at(i)=NULL;
had compiled, what would actually happen would be the following:
这种抱怨是有帮助的:即使编译器不会抱怨,代码也几乎可以肯定不会违背您的意图。该return
语句返回对象的副本data[i]
。因此,如果该语句payment.at(i)=NULL;
已编译,实际会发生以下情况:
- The internal object
data[i]
(or however you called it in your code) is copiedand the temporary copy returned. - The statement assigned that temporary copy, but leaves the original object in
MyVector
unchanged. - The temporary copy gets destructed, leaving no trace of your assignment.
- 内部对象
data[i]
(或您在代码中调用它的方式)被复制并返回临时副本。 - 该语句分配了该临时副本,但保留原始对象
MyVector
不变。 - 临时副本被破坏,你的任务没有留下任何痕迹。
This is almost certainly not what you wanted. You wanted to change the internal object. To do so, you have to return a referenceto that object. A reference refers to the object it was initialized with instead of making a copy. Correspondingly, a reference, even when returned, is an lvalue (since C++11 there's a second type of reference which behaves differently, but we don't need to care about that here). Your corrected function then reads
这几乎肯定不是您想要的。您想更改内部对象。为此,您必须返回对该对象的引用。引用指的是初始化它的对象,而不是复制它。相应地,一个引用,即使在返回时,也是一个左值(从 C++11 开始,有第二种类型的引用,它的行为有所不同,但我们不需要在这里关心它)。您更正后的功能然后读取
template<typename T>
T& MyVector<T>::at(int i)
{
return data[i];
}
and with that definition, payment.at(i)=NULL;
not only compiles, but actually does what you want: Change the internally stored i
-th pointer in payment
to NULL
.
使用该定义,payment.at(i)=NULL;
不仅可以编译,而且实际上可以执行您想要的操作:将内部存储的i
-th 指针更改payment
为NULL
.
回答by Silex
Your function MyVector::at(unsigned)
is probably not correctly declared and looks like this:
您的函数MyVector::at(unsigned)
可能未正确声明,如下所示:
T MyVector::at(unsigned i) { /* implementation detail */ }
What you want is for it to look like this:
你想要的是它看起来像这样:
T& MyVector::at(unsigned i) { /* implementation detail */ }
Notice the reference parameter (&), which will return whatever element by reference and allow the expression to be used as an l-value.
请注意引用参数 (&),它将通过引用返回任何元素,并允许将表达式用作左值。
The real question is why aren't you use std::vector
instead?
真正的问题是你为什么不使用它std::vector
?
回答by Lochemage
the term l-value in c++ means the 'left-value' is of the improper type. Since you are using the assignment operator on it, to be the proper type it must be a value that can be assigned a new value, which means it can not be a constant. Most likely, your call to payroll.at()
is returning a constant value instead of a reference to the actual value. Trying to assign a new value to it will then cause an l-value error.
C++ 中的术语 l 值意味着“左值”的类型不正确。由于您在其上使用赋值运算符,因此要成为正确的类型,它必须是可以分配新值的值,这意味着它不能是常量。最有可能的是,您对 的调用payroll.at()
返回的是一个常量值,而不是对实际值的引用。尝试为其分配新值将导致左值错误。