[英]Random access iterators - does vector.end() - vector.begin() = vector.size() in C++;
[英]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.