KQb*_*all 5 c++ templates vector
看看有关错误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
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么会抛出这个错误.在这个项目中,我将driver.cpp从一组员工对象指针更改为我制作的自定义Vector模板.我将Vector声明如下......
//Declare an Vector to hold employee object pointers
MyVector <employee*> payroll;
Run Code Online (Sandbox Code Playgroud)
任何帮助表示赞赏......
Moh*_*oun 12
抛出此错误的原因与您无法执行此操作的原因相同:
36 = 3;
Run Code Online (Sandbox Code Playgroud)
您的版本Vector::at应该返回引用而不是值.
左值称为左值,因为它们可以出现在赋值的左侧.Rvalues不能出现在左侧,这就是我们称之为rvalues的原因.你不能分配3,36因为36它不是左值,它是一个右值,一个临时值.它没有内存地址.出于同样的原因,你不能分配NULL给payroll.at(i).
你的定义:
template <class V> V MyVector<V>::at(int n)
Run Code Online (Sandbox Code Playgroud)
应该是什么:
template<typename V> V& MyVector::at(std::size_t n)
template<typename V> const V& MyVector::at(std::size_t n) const
Run Code Online (Sandbox Code Playgroud)
消息说您尝试分配给不是左值的表达式.对于内置类型,则只能分配给左值(这就是这个名字来源于:左值=值可以在左侧的赋值运算符的右手边,而右值=值必须在右边的右手边赋值运算符).
那么左值或左值是多少?请考虑以下代码:
int a;
a = 3;
Run Code Online (Sandbox Code Playgroud)
在这个赋值中a是一个左值(如果不是,编译器就会抱怨).也就是说,表达式a指的是可以修改的对象.另一方面,3是一个右值,即基本上是一个值.当然你不能分配给3; 编译器会3=a;在您的代码中使用完全相同的消息来抱怨该语句.
因此,作为第一近似,左值指定对象,而右值指定值.请注意,对于表单的分配也是如此
a = b;
Run Code Online (Sandbox Code Playgroud)
其中b也是一个变量.这里发生的是所谓的左值转换左值:分配的不是对象b,而是它的当前值.
现在考虑以下情况:
int f();
f() = 3;
Run Code Online (Sandbox Code Playgroud)
在这里你可能会争辩说函数f会返回一个对象(如果你使用一些用户定义的类型,你甚至可以看到它的构造/破坏).但编译器仍然抱怨你得到的消息.为什么?
好吧,即使您考虑f返回一个对象,它也是一个临时对象,它会立即消失.因此,分配一个值没有多大意义,因为无论如何你都无法对它做任何事情.
因此,这是第二条规则:
只要有一个表达式产生一个临时对象,C++就会将该表达式定义为rvalue.
现在我们来看MyVector::at()你没有展示的定义,但根据错误信息,它可能看起来与此类似:
template<typename T>
T MyVector<T>::at(int i)
{
return data[i];
}
Run Code Online (Sandbox Code Playgroud)
这与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];
}
Run Code Online (Sandbox Code Playgroud)
并且使用该定义,payment.at(i)=NULL;不仅可以编译,而且可以实际执行您想要的操作:将内部存储的i-th指针更改payment为NULL.