2015-01-10 97 views
2

我的問題很簡單。我有一個值的向量(線程在這裏,無關),我想遍歷它們。然而,有兩個版本的代碼看起來是一樣的,但只有第二個代碼可以工作。我想知道爲什麼。用括號括起來的C++解引用(帶迭代器)

版本1(不編譯)

int main(){ 
    int someValue = 5; 
    vector<std::thread *> threadVector; 

    threadVector.resize(20); 

    for (int i = 0; i < 20; i++) { 
     threadVector[i] = new std::thread(foo, std::ref(someValue)); 
    } 

    for (std::vector<std::thread *>::iterator it = threadVector.begin(); it != threadVector.end(); ++it) { 
     *it->join(); // *********Notice this Line********* 
    } 

    system("pause"); // I know I shouldn't be using this 
} 

2版(沒有工作)

int main(){ 
    int someValue = 5; 
    vector<std::thread *> threadVector; 

    threadVector.resize(20); 

    for (int i = 0; i < 20; i++) { 
     threadVector[i] = new std::thread(foo, std::ref(someValue)); 
    } 

    for (std::vector<std::thread *>::iterator it = threadVector.begin(); it != threadVector.end(); ++it) { 
     (*it)->join(); // *********Notice this Line********* 
    } 

    system("pause"); // I know I shouldn't be using this 
} 
+1

不僅使用'system(「pause」)'有問題,而且知道並且仍然發佈這個不相關的代碼留下了改進的餘地。 ;)這就是說,我認爲std :: thread是可移動的,因此可以存儲在一個容器中(比如早期的boost :: thread)。我可能會誤解,因爲我還沒有玩過C++ 11。 –

+0

那麼你能解釋一下將它們存儲在一個向量中有什麼問題嗎?我的意思是我可以聲明一個unique_ptr,然後std :: move到vector中,但這與新聲明有什麼不同? – JohnJohn

+0

我所建議的根本不是使用指針和動態分配,而是針對所有異常安全問題以及此類其他開銷。同樣,你不會使用「vector 」,而是使用「vector 」,或者?不過,我不確定你是否真的可以避免這種情況。 –

回答

2

這是一個問題與操作的順序。

*it->join(); 

被解析爲:

*(it->join()); 
+0

找到[此鏈接](http://en.cppreference.com/w/cpp/language/operator_precedence),你是對的。 – JohnJohn

1

以它作爲一種挑戰,我只是擦了擦我的腳在C++ 11的第一次。我發現,你可以達到同樣沒有std::thread對象的任何動態分配:

#include <iostream> 
#include <thread> 
#include <vector> 

void function() 
{ 
    std::cout << "thread function\n"; 
} 

int main() 
{ 
    std::vector<std::thread> ths; 
    ths.push_back(std::move(std::thread(&function))); 
    ths.push_back(std::move(std::thread(&function))); 
    ths.push_back(std::move(std::thread(&function))); 

    while (!ths.empty()) { 
     std::thread th = std::move(ths.back()); 
     ths.pop_back(); 
     th.join(); 
    } 
} 

這工作,因爲std::thread有一個構造函數和賦值操作符服用右值引用,使得它移動。此外,所有容器都獲得了對存儲可移動對象的支持,並且它們移動而不是在重新分配時複製它們。閱讀一些關於這個新的C++ 11功能的在線文章,這裏有太多的解釋,我也不太清楚。

關於你提出的問題,線程有內存成本,我不認爲你的方法是一個優化。而動態分配本身在內存和性能方面都有開銷。對於小對象,一個或兩個指針加上可能的一些填充的內存開銷是巨大的。如果std::thread對象只有一個指針的大小,那麼我不會感到驚訝,這會給您帶來超過100%的開銷。

請注意,這隻涉及std::thread對象。實際線程所需的內存,特別是其堆棧,是一個不同的問題。但是,std::thread對象和實際線程不具有1:1關係,並且std::thread對象的動態分配也不會更改任何內容。

如果您仍然擔心重新分配太貴,您可以預先保留合適的大小以避免重新分配。但是,如果這確實是一個問題,那麼您創建和終止線程的方式太多了,而這將遠遠超過轉移一些小物體的開銷。考慮使用線程池。

相關問題