查看有关错误C2106的其他问题,我仍然对代码的问题感到遗憾。编译时我收到以下错误:
c:\ driver.cpp(99):错误C2106:' =' :左操作数必须是l值
c:\ driver.cpp(169):错误C2106:' =' :左操作数必须是l值
代码行如下:
payroll.at(i) = NULL; //Line 99
payroll.at(count++) = ePtr; //Line 169
我无法理解为什么会抛出此错误。在这个项目中,我将driver.cpp从一组员工对象指针更改为我制作的自定义Vector模板。我将Vector声明如下......
//Declare an Vector to hold employee object pointers
MyVector <employee*> payroll;
感谢任何帮助...
答案 0 :(得分:12)
出现此错误的原因与您无法执行此操作的原因相同:
36 = 3;
您的Vector::at
版本应该返回引用而不是值
左值称为左值,因为它们可以出现在赋值的左侧。 Rvalues不能出现在左侧,这就是我们称之为rvalues的原因。您无法将3
分配给36
,因为36
不是左值,它是右值,是临时值。它没有内存地址。出于同样的原因,您无法将NULL
分配给payroll.at(i)
。
您的定义:
template <class V> V MyVector<V>::at(int n)
应该是什么:
template<typename V> V& MyVector::at(std::size_t n)
template<typename V> const V& MyVector::at(std::size_t n) const
答案 1 :(得分:5)
消息说您尝试分配给不是左值的表达式。对于内置类型,您只能分配给左值(名称来自的位置:左值=可以在赋值运算符的左侧手侧的值,而rvalue =必须为的值)在赋值运算符的右指针侧。)
那么左值或左值是多少?请考虑以下代码:
int a;
a = 3;
在这个赋值a
中是一个左值(如果不是,编译器就会抱怨)。也就是说,表达式a
指的是可以修改的对象。另一方面,3
是一个右值,即基本上是一个值。当然你不能分配给3
;编译器会抱怨语句3=a;
与您在代码中得到的消息完全相同。
因此,作为第一近似值,左值指定对象,而右值指定值。请注意,对于表单
的分配也是如此a = b;
其中b
也是变量。这里发生的是所谓的左值转换左值:分配的不是对象b
,而是它的当前值。
现在考虑以下情况:
int f();
f() = 3;
在这里你可能会争辩说函数f
会返回一个对象(如果你使用某种用户定义的类型,你甚至可以看到它的构造/破坏)。但编译器仍然抱怨你得到的消息。为什么呢?
好吧,即使您考虑f
返回一个对象,它也是一个临时对象,它会立即消失。因此,分配一个值没有多大意义,因为之后无论如何都无法做任何事情。
因此,这是第二条规则:
每当有一个产生临时对象的表达式时,C ++将该表达式定义为rvalue。
现在我们来看一下你没有展示的MyVector::at()
的定义,但根据错误信息,它可能看起来与此相似:
template<typename T>
T MyVector<T>::at(int i)
{
return data[i];
}
这与上面f
的格式基本相同,因为它还会返回T
(在您的情况下为employee*
)。这就是编译器抱怨的原因。
这个抱怨很有帮助:即使编译器不会抱怨,代码也不会像你几乎肯定想要的那样。 return
语句返回对象data[i]
的副本。因此,如果语句payment.at(i)=NULL;
已编译,实际发生的将是以下内容:
data[i]
(或者您在代码中调用它)是复制并返回临时副本。MyVector
不变。这几乎肯定不是你想要的。您想要更改内部对象。为此,您必须将引用返回给该对象。引用引用它初始化的对象而不是复制。相应地,引用,即使返回,也是左值(因为C ++ 11有第二种类型的引用,行为不同,但我们不需要在此处理)。您更正后的功能将读取
template<typename T>
T& MyVector<T>::at(int i)
{
return data[i];
}
根据该定义,payment.at(i)=NULL;
不仅可以编译,而且可以实际执行您想要的操作:将i
中内部存储的payment
指针更改为NULL
。< / p>
答案 2 :(得分:3)
您的函数MyVector::at(unsigned)
可能未正确声明,如下所示:
T MyVector::at(unsigned i) { /* implementation detail */ }
你想要的是它看起来像这样:
T& MyVector::at(unsigned i) { /* implementation detail */ }
注意引用参数(&amp;),它将通过引用返回任何元素,并允许表达式用作l值。
真正的问题是,为什么不使用std::vector
呢?
答案 3 :(得分:0)
c ++中的术语l值表示'left-value'属于不正确的类型。由于您在其上使用赋值运算符,因此它必须是可以赋予新值的值,这意味着它不能是常量。最有可能的是,您对payroll.at()
的调用返回的是常量值,而不是对实际值的引用。尝试为其分配新值将导致l值错误。