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的主要内容,如果未能解决你的问题,请参考以下文章

每日算法刷题-DFS题目

每日算法刷题-DFS题目

443M衣架遥控arduino代码备档

如何修改蒙版以使其成为完美的圆形

如何从文件中读取二维数组的元素数?

棋盘游戏的 int 数组