2014-06-18 63 views
-6

是否std::sort假設它能夠正確地工作,如果它得到一個空的範圍?std ::排序在空向量

我得到一個分段錯誤(GCC 4.8.3),此代碼:

std::vector<float> f; 
std::sort(f.begin() + 1, f.end()); 

標準說,對於空載體begin()end()返回相同的值。所以我預計sort在上述情況下什麼也不做,因爲它應該得到一個空的範圍:begin()+1應該大於end()

有這個空範圍排序沒有問題:

std::sort(f.begin(), f.end()); 
+4

那麼'f.begin()+ 1'呢?那不是越界嗎? – juanchopanza

+0

@juanchopanza它有一些價值,重要的是'begin()+ 1'是'end()'。 – user2052436

+4

這是一個值是無效的迭代器。它不是'>'或'<''而不是'end()'。這是無效的。 – juanchopanza

回答

1

f.begin()+1是出界,這是一個用於分割故障的原因。

使用f.begin()作爲數組的開始,並且這將是安全使用的。

+0

好吧,爲了排除第一個元素,我需要在調用'sort'前檢查'size()> 0'。 – user2052436

+0

是的,這是正確的。 – pippin1289

+0

謝謝,pippin1289 – user2052436

3

std::sort預計[begin, end)是一個有效的範圍,如果您繼續增加begin您最終將達到end。在你的情況下,begin()+1已經過去了end(),所以std::sort無法知道它正在經過該範圍的末尾。

std::sort需要迭代器,而不是指針。正因爲如此,它無法運行begin < end檢查:如果您通過兩個迭代器的rbegin()rend(),則會失敗。

如果您想對排除最初元素的std::vector部分進行排序,您需要確保容器不是空的。否則,begin()+1將產生無效的迭代器。

注意:雖然從技術角度而言,當您在空容器上執行begin()+1時發生未定義的行爲,但您的案例中的崩潰幾乎肯定來自std::sort中的取消引用。另請注意,如果您有C++ 11兼容的編譯器,則使用std::next(v.begin(), 1)優於v.begin() + 1。上輸入迭代

+1

你不會去std :: sort,它早就結束了。 – Deduplicator

+0

好吧,現在你也說出了實際的錯誤,我改變了我的投票。 – Deduplicator

2

遞增具有前提迭代器必須提領。對於空向量,v.begin()不可解引用,因此試圖執行v.begin() + 1(反過來以增量的方式定義)是未定義的行爲。

此外,std::sort(begin, end)要求[begin, end)是一個有效的範圍內,並且所述標準說(§24.2.1[iterator.requirements.general]/P7)

範圍[i,j)是有效的,當且僅當ji可到達。將庫中的函數應用於無效範圍的結果未定義。

對於大多數隨機訪問迭代(<>爲其定義的迭代器的唯一類型),如果a > b然後a不是來自b可達,所以[a, b)確實表示空範圍 - 它不根本不表示有效範圍。

+0

@Deduplicator ...這是第一段? –

+0

@Dupuplicator UB並不總是直接顯示。在這裏,segfault可能來自'it!= end',所以解除引導'begin + 1'(指向無效內存,是的)會發生,所以繁榮。是的,從技術上講,該節目在'v.begin()+ 1'展出UB,但其他方面也很重要。 – stefan

+0

@Deduplicator'v.begin()+ 1'是未定義行爲的原因正是因爲'v.begin()'不可解引用,並且您有違反前提條件。 –