簡體   English   中英

函數返回struct為LValue

[英]Function returning struct as LValue

在下面的代碼片段中,為什么行o.margin() = m; 編譯無故障? 它很容易引起警告,因為它幾乎總是一個錯誤。 我實際上認為它是一個錯誤,因為它在賦值的左側放置了一個R值。

#include <iostream>

struct Margin
{
    Margin(int val=0) : val(val) {};
    int val;
};

struct Option
{
    Margin m;
    int z=0;

    Margin margin()const { return m; }
    int zoomLevel() { return z; }
};


int main()
{
    Option o;
    std::cout << "Margin is: "<< o.margin().val << std::endl;

    Margin m = { 3 };

    // The following line is a no-op, which generates no warning:
    o.margin() = m;

    // The following line is an error
    // GCC 4.9.0: error: lvalue required as left operand of assignment
    // clang 3.8: error: expression is not assignable
    // MSVC 2015: error C2106: '=': left operand must be l-value
     o.zoomLevel() = 2;

    std::cout << "Margin is: "<< o.margin().val << std::endl;

    return 0;
}

輸出:

Margin is: 0
Margin is: 0

您可以修改類類型的返回類型(通過調用非const方法):

3.10 / 5來自n4140

5為了修改對象,對象的左值是必要的,除了在某些情況下也可以使用類類型的右值來修改它的指示對象。 [示例:調用對象(9.3)的成員函數可以修改對象。 - 末端的例子]

你的代碼:

o.margin() = m;

實際上是一樣的

o.margin().operator=( Margin(m) );

因此,如果將其更改為:const const方法,則調用它:

o.margin().val = m;

然后你會得到一個錯誤。

另一方面,這里:

o.zoomLevel()= 2;

zoomLevel()返回非類類型,因此您無法修改它。

o是類類型的對象時, operator=是成員函數。 代碼o.margin() = m; 相當於o.margin().operator=(m);

您可以調用臨時類對象的成員函數,類似於訪問o.margin().val的成員的o.margin().val

此外,類的賦值運算符可以被覆蓋,而根本不是無操作符。

如果你想禁止這樣的用法,那么從C ++ 11開始,你可以在賦值運算符上使用引用限定符

Margin& operator=(const Margin&) & = default;

這將在GCC 5.1上生成以下錯誤:

error: passing 'Margin' as 'this' argument discards qualifiers [-fpermissive]

您可能還想查看此相關問題

Option::margin()是一個const 可訪問的成員函數,它返回一個可變的Margin對象。

因此,分配臨時值是有效的,因為使用operator= on Margin是有效的。 在這種情況下,它沒有副作用,基本上什么也沒做。 C ++編譯器的特定實現可以選擇實現語義分析並警告您,但它完全超出了語言的范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM