当我编译下面的代码时,我得到“错误C2106:'=':左操作数必须是l-value”at“m.msg_body [i] .id = i;”。当我注释掉那一行时,没有错误。我的代码出了什么问题?
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";
}
}
答案 0 :(得分:5)
您的operator[]
按值返回,这意味着它会生成一个临时副本并返回该值。临时陪审员是价值。您应该修改运算符以返回引用。实际上,你应该有两个版本,一个const版本,它返回一个const引用,一个非const版本,它返回一个非const引用。
您处理超出范围索引的方法必须改变。您可以抛出异常,或者只是将其保留为未定义的行为,只需确保记录它。另一个选择是在类中有一个伪MsgBodyData
对象,当你得到一个坏索引时,你会返回该对象,但这似乎是一个非常愚蠢的设计。
答案 1 :(得分:3)
您的operator[]
会返回一个临时值(右值),使其每个成员都成为 rvalue 。该语言禁止分配给右值(准确地说,分配给非类型的右值),这就是错误告诉你的。
这种限制的原因在于,由于左侧将在完整表达式的末尾被销毁,因此赋值将没有多大意义(临时破坏将会忘记它)。
如果您打算修改类中保存的元素,则需要将引用( lvalue )返回到存储的元素,而不是副本。