2010-02-09 23 views
-3

看看下面簡單的代碼:爲什麼string :: append操作行爲奇怪?

#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string s("1234567890"); 
    string::iterator i1 = s.begin(); 
    string::iterator i2 = s.begin(); 
    string s1, s2; 
    s1.append(i1, ++i1); 
    s2.append(++i2, s.end()); 

    cout << s1 << endl; 
    cout << s2 << endl; 
} 

你所期望的輸出是什麼?

,你會和我一樣,希望它是:

1 
234567890 

錯了! 它是:

234567890 

即第一個字符串是空的。

前綴增加運算符的接縫對迭代器有問題。或者我錯過了什麼?

+7

I我不是這裏的downvoters之一,但我建議他們從你的建議中找到你找到了一個編譯器錯誤。每個人都有一個「我發現了一個<真正重要的東西>的錯誤?」很早的時候(在我的情況下,這是libm),他們都是錯的。如果你確實發現了一個大量使用它的bug,那麼在你對這個工具有很多經驗之後你會發現一個bug。 – dmckee 2010-02-09 17:51:27

+2

爲什麼downvotes?海灣合作委員會的開發人員是否充滿個人暗示? (我的意思是* GCC的開發者*) – Manuel 2010-02-09 17:51:56

+2

@Manuel:因爲問題的方式而下降。請參閱http://catb.org/~esr/faqs/smart-questions。html#id382249。即使這是一個錯誤,但這不是錯誤報告的正確論壇。標題是無用的通用名稱。至少有一個很好的repro配方。 – user9876 2010-02-09 17:55:57

回答

3

不是一個錯誤。

的順序,其中所述參數

s1.append(i1, ++i1); 

評價不是由標準指定。編譯器可以自由使用它選擇的任何順序。在這種情況下,它將在第一個參數(i1)之前評估第二個參數(++i1),並指定要複製的零範圍。

8

C++實現可以以任意順序自由評估參數。在這種情況下,如果首先評估++ i1,則會得到一個空字符串。

3

C++標準沒有規定任何關於函數參數被評估的順序,使得它依賴於實現。 C++要求函數的參數在輸入函數之前被完全評估(並且發佈所有副作用),但實現可以自由地以任何順序評估參數

在你的情況下,i++在做出參數相同,導致一個空字符串。在這裏這種行爲

更多信息上comp.compilers newsgroup

14

你錯過了一些東西:這真的和迭代器無關。未指定函數參數的評估順序。因此,您的:append(i1, ++i1);將取決於未指定的行爲,而不管i1的類型如何。只是舉例,給出更簡單的東西很多,如:

void print(int a, int b) { 
    std::cout << a << " " << b << "\n"; 
} 

int main() { 
    int a =0; 
    print(a, ++a); 
    return 0; 
} 

你的產量可能完全有理由成爲「0 1」你似乎期望,但它也可能完全有理由爲:「1 + 1」。由於這是未指定的,它可能會從編譯器的一個版本更改爲下一個版本,甚至在您更改標誌時使用相同的編譯器,或者(理論上)可能因月亮的相位而異...