2

次のコードをコンパイルすると、「m.msg_body[i].id = i;」で「エラー C2106: '=' : 左オペランドは左辺値でなければなりません」というメッセージが表示されました。その行をコメントアウトすると、エラーはありません。コードの何が問題になっていますか?

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

2 に答える 2

5

つまりoperator[]、一時的なコピーを作成してそれを返します。一時的な値は右辺値です。参照を返すように演算子を変更する必要があります。実際には、const 参照を返す const バージョンと、非 const 参照を返す非 const バージョンの 2 つのバージョンが必要です。

ただし、範囲外のインデックスを処理する方法は変更する必要があります。例外をスローするか、単に未定義の動作のままにしておくことができますが、必ず文書化してください。もう 1 つのオプションは、不適切MsgBodyDataなインデックスを取得したときに返すクラスにダミー オブジェクトを含めることですが、これは非常にばかげた設計のように思えます。

于 2012-08-08T04:24:03.363 に答える
3

Youroperator[]は一時的な (右辺値) を返します。これにより、そのメンバーのそれぞれが右辺値になります。この言語では、右辺値への代入 (正確には、非クラス型の右辺値への代入) が禁止されており、それがエラーが伝えていることです。

その制限の理由は、左側が完全な式の最後で破棄されるため、代入があまり意味をなさないためです (一時的な破棄で忘れられます)。

クラス内に保持されている要素を変更するつもりだった場合は、コピーではなく、保存されている要素への参照 ( lvalue ) を返す必要があります。

于 2012-08-08T04:24:02.317 に答える