0
Posted
技术标签:
【中文标题】'=' : 左操作数必须是左值【英文标题】:'=' : left operand must be l-value 【发布时间】:2012-08-08 04:20:01 【问题描述】:当我编译以下代码时,在“m.msg_body[i].id = i;”处出现“错误 C2106: '=' : left operand must be l-value”。当我注释掉该行时,没有错误。我的代码有什么问题?
static const short MSG_DATA_MAX = 10;
struct MsgBodyData
int id;
string value;
;
class MsgBody
public:
MsgBody()
len = 0;
MsgBody(MsgBody & msg_obj);
~MsgBody()
int length() return len;
void setLength(int _len) len = _len;
MsgBodyData operator[](short index)
if(index > -1 && index < MSG_DATA_MAX)
return data[index];
MsgBodyData dump_data;
return dump_data;
void operator=(MsgBody & msg_obj)
len = msg_obj.length();
for(int i = 0; i < len; ++i)
data[i] = msg_obj[i];
private:
int len;
MsgBodyData data[MSG_DATA_MAX];
;
MsgBody::MsgBody(MsgBody &msg_obj)
operator=(msg_obj);
struct Msg
int msg_id;
string msg_title;
MsgBody msg_body;
;
void sendMsg()
Msg m;
m.msg_id = 1;
m.msg_title = "test_msg";
int size = MSG_DATA_MAX;
for(int i = 0; i < size; ++i)
m.msg_body[i].id = i; // HERE I GOT ERROR !!!
m.msg_body[i].value = "test_value";
【问题讨论】:
【参考方案1】:您的operator[]
按值返回,这意味着它会制作一个临时副本并返回该副本。临时变量是右值。您应该修改您的运算符以返回参考。实际上,您应该有两个版本,一个 const 版本,它返回一个 const 引用,一个非常量版本,它返回一个非常量引用。
不过,您处理超出范围索引的方法将不得不改变。您可以抛出异常,也可以简单地将其保留为未定义的行为,只要确保将其记录在案即可。另一种选择是在类中有一个虚拟的 MsgBodyData
对象,当您获得错误索引时返回该对象,但这似乎是一个非常愚蠢的设计。
【讨论】:
在抛出异常后,我可以只为超出范围的索引返回 NULL 吗? 如果你抛出异常,你不会返回任何东西。 @LwinHtooKo:你的MsgBodyData
如何转换为NULL?即使可以,那仍然是一个右值。 在抛出异常之后?没有意义,因为永远不会到达 return 语句。
@LwinHtooKo:因为value
的类型是std::string
。一个类,而不是内置的。可以(尽管不推荐)为一个除了赋值给对象之外有一些副作用的类编写赋值运算符。在这种情况下,分配给右值可能是有意义的。我猜标准委员会决定简单地允许它全面允许,而不是要求编译器分析赋值运算符的这些副作用。 (这是一个猜测,我实际上不知道标准委员会的推理是什么)【参考方案2】:
您的operator[]
返回一个临时的(右值),这使得它的每个成员都成为一个右值。该语言禁止分配给右值(准确地说,是分配给非类类型的右值),这就是错误告诉您的内容。
这种限制的原因是,由于左侧将在完整表达式的末尾被销毁,因此分配没有多大意义(它会随着临时销毁而被遗忘)。
如果您打算修改类中保存的元素,则需要返回对存储元素的引用 (lvalue),而不是副本。
【讨论】:
以上是关于0的主要内容,如果未能解决你的问题,请参考以下文章