2012-02-29 57 views
3

也許這是一個非常愚蠢的問題,但是我正在閱讀的這本書指示我編寫一段代碼,該代碼使用算法對矢量中的元素進行加擾和排序。爲此,本書告訴我使用主C++庫中的算法庫。好吧,到目前爲止我明白了,但是在編寫代碼之後,我想看看如果我從代碼的頂部刪除這個庫,會發生什麼情況,並且讓我感到驚訝的是,一切仍然有效。刪除'#include <algorithm>'不會破壞代碼

這是我正在談論的代碼。當我從代碼的頂部刪除'#include algorithm'時,沒有任何內容會被打破。怎麼會這樣?不使用這個庫時,'random_shuffle'部分是不是應該破壞?

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <ctime> 
#include <cstdlib> 
using namespace std; 

int main() 
{ 
    vector<int>::const_iterator iter; 

    cout << "Creating a list of scores."; 
    vector<int> scores; 
    scores.push_back(1500); 
    scores.push_back(3500); 
    scores.push_back(7500); 

    cout << "\nHigh Scores:\n"; 
    for (iter = scores.begin(); iter != scores.end(); ++iter) 
    { 
     cout << *iter << endl; 
    } 

    cout << "\nFinding a score."; 
    int score; 
    cout << "\nEnter a score to find: "; 
    cin >> score; 
    iter = find(scores.begin(), scores.end(), score); 
    if (iter != scores.end()) 
    { 
     cout << "Score found.\n"; 
    } 
    else 
    { 
     cout << "Score not found.\n"; 
    } 

    cout << "\nRandomizing scores."; 
    srand(static_cast<unsigned int>(time(0))); 
    random_shuffle(scores.begin(), scores.end()); 
    cout << "\nHigh Scores:\n"; 
    for (iter = scores.begin(); iter != scores.end(); ++iter) 
    { 
     cout << *iter << endl; 
    } 

    cout << "\nSorting scores."; 
    sort(scores.begin(), scores.end()); 
    cout << "\nHigh Scores:\n"; 
    for (iter = scores.begin(); iter != scores.end(); ++iter) 
    { 
     cout << *iter << endl; 
    } 

    system("pause"); 
    return 0; 
} 
+0

哪個編譯器?如果我在VS2010中刪除'#include ',它將無法編譯。 – Naveen 2012-02-29 12:00:20

+0

我正在使用NetBeans IDE 7.1和M​​inGW。 – DutchLearner 2012-02-29 12:05:46

回答

7

它的工作原理是因爲已被列入由您還包括一個頭的原因。

例如,向量可能包含了源代碼中的算法。這很常見,因爲它們通常只是標題。

也就是說,你不能依賴標準庫的具體實現來在每個頭中包含相同的內容。 (例如可能與MSVC一起工作,它可能會與gcc stdlibC+++斷開)。

由於這個原因,我強烈建議包括你使用的東西,而不管它在哪裏編譯。 ---注意這與'你所引用的'略有不同,因爲頭部中的點和引用的前向聲明可以顯着提高構建時間。

0

休息這裏

[email protected]:~$ g++ test.cpp 
test.cpp: In function ‘int main()’: 
test.cpp:27:52: error: no matching function for call to ‘find(std::vector<int>::iterator, std::vector<int>::iterator, int&)’ 
test.cpp:27:52: note: candidate is: 
/usr/include/c++/4.6/bits/streambuf_iterator.h:359:5: note: template<class _CharT2> typename __gnu_cxx::__enable_if<std::__is_char<_CharT2>::__value, std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> > >::__type std::find(std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >, std::istreambuf_iterator<_CharT2, std::char_traits<_CharT> >, const _CharT2&) 
test.cpp:39:48: error: ‘random_shuffle’ was not declared in this scope 
test.cpp:47:38: error: ‘sort’ was not declared in this scope 
[email protected]:~$ 

GCC 4.6.1

+0

不在這裏,也許你正在使用不同的IDE? – DutchLearner 2012-02-29 12:01:46

+0

不是「這怎麼可能?」的答案 – 2012-02-29 12:10:47

+0

@phresnel如果推定不成立,那麼回答它的方式是沒有意義的。也許OP是使用奇怪的編譯器標誌。我堅持認爲,看到不同的編譯器如何給他一個不同的結果,可能會回答一些問題,例如標題中包含的標題不是由標準決定的。 – 2012-02-29 12:37:21

3

C++標準並不規定每個標準頭包含哪些頭。這意味着,例如,<vector>可能爲#include <algorithm>用於庫實現A,但不在庫實現B中。這可能也會在同一庫的不同版本之間或不同端口上發生變化。例如,一旦glibC++清理了其包含的層次結構,

這使我們對C++程序員有些不適,因爲我們應該確保包含正確的程序員,即使某些標準頭文件已經這樣做;如果我們懶惰,我們冒着編譯在其他平臺上崩潰的風險,系統升級和降級。

經驗法則:

包括什麼是必要的,因爲每頭的定義。但不是更多。

「但不是更多」,因爲編譯時間可能會變得非常緩慢。

+0

非常清楚,謝謝。 :) – DutchLearner 2012-02-29 12:10:28

+0

_「我們冒着編譯在其他平臺上崩潰的風險」_或者當你編寫'apt-get upgrade gcc'時。 – 2016-04-21 13:39:08

+0

@LightnessRacesinOrbit:這包括在我自己的,非常抽象的,非常嚴格的術語「平臺」中。升級之後,這是另一個平臺。但我會將其添加到我的答案中。 – 2016-04-21 14:19:23

0

當我刪除#include算法行時,代碼無法編譯。冒着聽起來非常光顧的風險,你確定你已經重新編譯了?

我的編譯器輸出:

a.cpp(28) : error C3861: 'find': identifier not found 
a.cpp(40) : error C3861: 'random_shuffle': identifier not found 
a.cpp(48) : error C3861: 'sort': identifier not found 
+0

我很確定。順便說一下,我使用的是NetBeans,也許這與我們的IDE有所不同? – DutchLearner 2012-02-29 12:04:04

+0

我只是使用命令行。自從我使用netbeans以來,它已經有一段時間了,但是我記得當時你必須在項目瀏覽器中右鍵單擊該類並單擊重新編譯。 (@phresnel:我認爲這是一個禮貌的措詞可能的答案,可能是這樣,他可能不知道包括需要重新編譯) – sji 2012-02-29 12:13:07

+0

哎呦,我在一次事故中判斷,我真的要發表我的評論somehwere其他,對不起。 – 2012-02-29 12:15:50

0

不幸的是,標準的頭被允許包括其他標準的頭,所以沒有保證,如果你忘記了一個你的代碼將打破。

0

#include預處理程序指令在鏈接過程中不「包含」庫,只是指示預編譯器讀取頭文件並將其包含在正在編譯爲單個單元的源文件中。

也就是說,algorithm頭文件可能包含在另一個包含文件中。

注意:可以聲明一個特定的函數或方法,並且在頭文件中定義了,所以它不需要鏈接。

編輯: 您的代碼寫得很好,應該按預期工作。我只建議你使用預定義的換行字符endl並把它列入在輸出序列的末尾,而不是在未來的開頭:

cout << "Creating a list of scores." << endl; 
cout << "High Scores:" << endl; 
1

代碼工作,因爲向量包括內部算法。 要驗證包含的內容和不包含的內容,可以通過將-E標誌傳遞給編譯器來生成預處理器輸出。

寫示例文件:temp.C它只有一行:

#include <vector> 

現在,如果我們編譯文件爲g++ -E temp.C,你將能夠在算法包括輸出看到。

+0

Upvote from me,但是我認爲使用g ++ temp.cpp -M – wreckgar23 2012-02-29 12:09:31

+1

包含算法(比如它適用於我)會更容易。請注意,它取決於庫實現;你不能依賴''包括''或其他任何東西(事實上,在我的特定實現中,它不)。 – 2012-02-29 12:11:55

+0

好的建議與-E標誌,但是,它不回答「這怎麼可能?」 – 2012-02-29 12:12:46