【问题标题】:'=' : 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";
    }
}

【问题讨论】:

    标签: c++


    【解决方案1】:

    您的operator[] 按值返回,这意味着它会制作一个临时副本并返回该副本。临时变量是右值。您应该修改您的运算符以返回参考。实际上,您应该有两个版本,一个 const 版本,它返回一个 const 引用,一个非常量版本,它返回一个非常量引用。

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

    【讨论】:

    • 在抛出异常后,我可以只为超出范围的索引返回 NULL 吗?
    • 如果你抛出异常,你不会返回任何东西。
    • @LwinHtooKo:你的MsgBodyData如何转换为NULL?即使可以,那仍然是一个右值。 抛出异常之后?没有意义,因为永远不会到达 return 语句。
    • @LwinHtooKo:因为value 的类型是std::string。一个类,而不是内置的。可以(尽管不推荐)为一个除了赋值给对象之外有一些副作用的类编写赋值运算符。在这种情况下,分配给右值可能是有意义的。我猜标准委员会决定简单地允许它全面允许,而不是要求编译器分析赋值运算符的这些副作用。 (这是一个猜测,我实际上不知道标准委员会的推理是什么)
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      相关资源
      最近更新 更多