7

查看有关错误 C2106 的其他问题,我仍然不知道我的代码有什么问题。编译时出现以下错误:

c:\driver.cpp(99): 错误 C2106: '=' : 左操作数必须是左值

c:\driver.cpp(169): 错误 C2106: '=' : 左操作数必须是左值

代码行如下:

payroll.at(i) = NULL; //Line 99
payroll.at(count++) = ePtr; //Line 169

我不明白为什么会抛出这个错误。在这个项目中,我将 driver.cpp 从一组员工对象指针更改为我制作的自定义 Vector 模板。我声明向量如下...

//Declare an Vector to hold employee object pointers
MyVector <employee*> payroll;

任何帮助表示赞赏...

4

4 回答 4

13

抛出此错误的原因与您不能执行以下操作的原因相同:

36 = 3;

您的版本Vector::at应该返回引用而不是值。
左值之所以称为左值,是因为它们可以出现在赋值的左侧。右值不能出现在左侧,这就是我们称它们为右值的原因。您不能分配给336因为36它不是左值,它是右值,是临时的。它没有内存地址。出于同样的原因,您不能分配NULLpayroll.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
于 2013-07-29T18:00:26.083 回答
6

该消息说您尝试分配给不是左值的表达式。对于内置类型,您只能分配给左值(这就是名称的来源:左值 = 可以在赋值运算符左侧的值,而右值 = 必须在右侧的值赋值运算符)。

那么什么是左值或右值?考虑以下代码:

int a;
a = 3;

在这个赋值a中是一个左值(如果不是,编译器会抱怨)。也就是说,表达式a指的是可以修改的对象。另一方面,3是一个右值,即基本上是一个值。当然你不能分配给3; 3=a;编译器会以与您在代码中得到的完全相同的消息来抱怨该语句。

因此,作为第一个近似值,左值表示一个对象,而右值表示一个值。请注意,这也适用于表单的分配

a = b;

其中b也是一个变量。这里发生的是所谓的左值到右值的转换:分配的不是对象b,而是它的当前值。

现在考虑以下情况:

int f();
f() = 3;

在这里您可能会争辩说该函数f确实返回了一个对象(如果您使用一些用户定义的类型,您甚至可以看到它的构造/销毁)。但是编译器仍然会抱怨您收到的消息。为什么?

好吧,即使您考虑f返回一个对象,它也是一个临时对象,会立即消失。因此,分配一个值没有多大意义,因为之后无论如何您都无法对它做任何事情。

因此,这是第二条规则:

只要有一个产生临时对象的表达式,C++ 就会将该表达式定义为右值。

现在我们来看看MyVector::at()您没有显示的定义,但根据错误消息,它可能看起来类似于:

template<typename T>
 T MyVector<T>::at(int i)
{
  return data[i];
}

这与上面的形式基本相同f,因为它还返回 a Temployee*在您的情况下为 an)。这就是编译器抱怨的原因。

这种抱怨是有帮助的:即使编译器不会抱怨,代码也不会像你几乎肯定想要的那样。该return语句返回对象的副本data[i]。因此,如果该语句payment.at(i)=NULL;已编译,实际发生的情况如下:

  1. 复制内部对象data[i](或者您在代码中调用它的任何方式)并返回临时副本。
  2. 该语句分配了该临时副本,但保持原始对象MyVector不变。
  3. 临时副本被破坏,没有留下你的任务痕迹。

这几乎肯定不是你想要的。您想更改内部对象。为此,您必须返回对该对象的引用。引用指的是它被初始化的对象,而不是复制。相应地,即使被返回,引用也是一个左值(从 C++11 开始,还有第二种类型的引用,其行为不同,但我们不需要在这里关心它)。然后您更正的函数显示为

template<typename T>
 T& MyVector<T>::at(int i)
{
  return data[i];
}

并且使用该定义,payment.at(i)=NULL;不仅可以编译,而且实际上可以执行您想要的操作:将内部存储的i-th 指针更改paymentNULL.

于 2013-07-29T20:28:53.173 回答
3

您的函数MyVector::at(unsigned)可能未正确声明,如下所示:

T MyVector::at(unsigned i) { /* implementation detail */ }

你想要的是它看起来像这样:

T& MyVector::at(unsigned i) { /* implementation detail */ }

请注意引用参数 (&),它将通过引用返回任何元素并允许将表达式用作左值。

真正的问题是你为什么不使用它std::vector呢?

于 2013-07-29T18:06:03.230 回答
0

c++ 中的术语 l-value 表示“左值”的类型不正确。由于您在其上使用赋值运算符,因此要成为正确的类型,它必须是可以分配新值的值,这意味着它不能是常量。最有可能的是,您的调用payroll.at()是返回一个常量值而不是对实际值的引用。尝试为其分配新值将导致左值错误。

于 2013-07-29T18:03:51.340 回答