簡體   English   中英

為什么編譯器允許C ++中的vector.begin()= vector.end()?

[英]Why does the compiler allow vector.begin()=vector.end() in C++?

在學習C ++中的 迭代器時 ,我嘗試了以下方法:

#include <vector>

int main() {
    std::vector<int> a;
    a.end()=a.begin();
    //Why is this even allowed by the compiler?
}

我錯過了什么?

如果例如函數end將返回指針,那么它將不可用。

例如,不會編譯此代碼

int a[] = { 1, 2, 3 };

std::end( a ) = std::begin( a );

GCC發出錯誤

error: lvalue required as left operand of assignment
  std::end( a ) = std::begin( a );
                ^

但是,當使用類類型的對象時,它們可以調用ovetloaded復制(或移動)賦值運算符。

所以問題出現了為什么函數不返回常量迭代器對象。 我認為應用operator ++是可能的。 例如

auto it = ++c.begin();

對於直接訪問迭代器作為指針,您可以簡單地編寫

auto it = begin( a ) + 1;

該標准未指定std::vector::iterator是類類型還是原始指針。

如果它是類類型,則此代碼在a.end()返回的臨時對象上調用operator= 不是一個非常有用的操作,但合法。 (Rvalues可能有調用它們的函數)。

如果你的庫使std::vector::iterator成為一個指針,那么這個代碼將無法編譯,因為簡單的賦值需要左邊的左值。

Jarod42指出,如果迭代器的賦值運算符被定義為:

std::vector::iterator& std::vector::iterator::operator =(std::vector::iterator) &;

那么這段代碼就是非法的; 尾隨&表示該函數僅在左值上調用時才可選。

但是沒有這樣定義,我猜想委員會不想因為沒有充分理由而使一些法律法規成為非法; 也許有一個用例,沒人想到。

該行影響臨時迭代器,因此沒用。

允許使用std::vector::iterator = std::vector::iterator

一種不允許的方式就是擁有

std::vector::iterator::operator =(std::vector::iterator) &; // note the extra &

但是std::vector::iterator可能是一個簡單的指針,我們不能拒絕T* = T*

您不能在C ++中分配rvalue(aka temporary)原語類型,如(int)7或函數返回的值。 這很有意義,因為賦值的結果會被立即丟棄,所以它可能不是程序員想要的。 rvalue表示語言語法中“ = sign”的右側,或臨時(匿名)值。

但是對於類類型的對象, =只調用operator= 通常當lhs是rvalue時,這沒有任何意義,但有時它會(比如,類是一個代理對象偽引用(就像std::vector<bool>上的[]返回)。所以它被對待特別是,它只調用方法。而且無法判斷方法是從臨時右值還是“真正的”左值調用的。

rvalue引用是C ++ 11中的新增內容,rvalue限定方法也是如此。

在C ++ 11之前,沒有辦法阻止在類類型的對象上調用operator=只是因為它是臨時的。

begin返回一個非const臨時,如果它是類類型(不是標准保證),它可以被賦值。

今天我們可以阻止分配給類類型的臨時代碼,但是標准庫還沒有被修改以阻止它的類型。 可能至少部分是為了避免向后兼容性問題,部分是為了首先確定std之外的最佳實踐。

它們是允許的,因為迭代器對象是可復制分配和可復制構造的。 這就是為什么我們可以做類似a.begin()= a.end()的事情。 此外,我們可以自動執行它(a.begin())。

請查看以下有關可復制的示例。

#include <vector>

struct CopyConsAssignable
{
    int x;
    CopyConsAssignable(int a) 
    { 
        x = a; 
    }

    CopyConsAssignable(const CopyConsAssignable& other)
    {
        x = other.x;
    }

    CopyConsAssignable& operator=(const CopyConsAssignable& other)
    {
        if (this != &other)
        {
            x = other.x;
        }
        return *this;
    }
};


int main()
{
    std::vector<int> a;
    a.begin() = a.end();

    CopyConsAssignable(2) = CopyConsAssignable(4); // Allowed as the objects are copy-assignable
    return 0;
}

暫無
暫無

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

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