'=' : 左操作数必须是 l 值

'=' : left operand must be l-value

本文关键字:操作数      更新时间:2023-10-16

当我编译以下代码时,我在"m.msg_body[i].id = i;"处得到"错误 C2106:'=':左操作数必须是 l 值"。当我注释掉那行时,没有错误。我的代码有什么问题?

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";
    }
}

您的operator[]按值返回,这意味着它会创建一个临时副本并返回该副本。 临时是右值。 应修改运算符以返回引用。 实际上,您应该有两个版本,一个是 const 版本,它返回一个 const 引用,另一个是 non-const 版本,它返回一个非 const 引用。

但是,处理超出范围索引的方法必须更改。 您可以抛出异常,也可以将其保留为未定义的行为,只需确保记录它即可。 另一种选择是在类中有一个虚拟的MsgBodyData对象,当你得到一个错误的索引时,你返回该对象,但这似乎是一个非常愚蠢的设计。

您的operator[]返回一个临时(右值),这使它的每个成员都成为右值。该语言禁止分配给右值(准确地说,分配给非类类型的右值),这就是错误告诉你的。

这种限制的原因是,由于左侧将在完整表达式的末尾被销毁,因此赋值没有多大意义(临时销毁时会忘记它)。

如果要修改类中保存的元素,则需要返回对存储元素的引用(左值),而不是副本。