2016-05-10 55 views
1

我經常閱讀我應該通過一個函數const引用shared_ptr,因爲它更快。當我想到它時,我不確定這是否是一個好的建議,因爲我不確定這是否是線程化的。任何人都可以告訴我,如果這將是通過const ref傳遞的線程嗎?它通過const引用傳遞shared_pointer線程嗎?

回答

1

你應該更喜歡通過const&來避免任何類的副本的開銷。例如,這對於像std::string這樣的東西特別重要。

在通過shared_ptrconst&的情況下,開銷主要是incrementing and decrementing of the reference count,因爲它是原子的。

但是!與const& shared_ptr創建線程時有一個問題:引用計數將遞增。既然它增加了,就好像你已經通過價值傳遞了它。你實際上是通過價值傳遞到std::thread ctor,從而增加,然後通過ref傳遞給函數。

見自己:

// gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4 
void test(const shared_ptr<int>& i) 
{ 
    cout << "c = " << i.use_count() << endl; 
} 

int main(int argc, char** argv) 
{ 
shared_ptr<int> i(new int); 
cout << "c = " << i.use_count() << endl; 
test(i); 

cout << "thread!" << endl; 
thread t(test, i); 
t.join(); 
cout << "c = " << i.use_count() << endl; 
} 

結果之中:

c = 1 
c = 1 
thread! 
c = 2 // <= incremented! 
c = 1 // <= thread joined! 

shared_ptr是線程安全的一個完美的候選人,但它不會保護你的比賽條件和死鎖。

+1

'std :: thread'構造函數複製/移動所有參數。 – GeorgeAl

+0

@GeorgeAl Thx,補充說,精度 – BlakBat

1

With a & you get the object itself。

你沒有增加參考數量,你只是通過它自己的對象。人們建議通過const&的原因是爲了避免線程安全增加參考計數的成本。作爲const&傳遞的代價與複製int或指針的代價相同,並且沒有臨時對象將被綁定到const&,因爲shared_ptr的構造函數標記爲explicit

而且由於您始終至少有一個對象引用(引用與被調用函數綁定的對象),所以不用擔心在使用本地引用時對象可能會被破壞。

+0

如果引用綁定的對象超出範圍會發生什麼?它不會被破壞,因爲refcount然後是0.如果這會發生,我會使用內存,如果我使用ref – Exagon

+0

傳遞一個'const&'與一個普通'&'不同?兩者都只是參考,所以不應引用計數更改。 – rozina

+0

@Exagon,它是如何超出範圍的?你調用了傳遞本地'shared_ptr'的函數。它至少不能超出範圍,直到你從該函數返回並且直到當前塊'shared_ptr'到達結尾。例如'{std :: shared_ptr my_shared = make_shared (...); pass_by_constref(my_shared);返回0; }' – GeorgeAl

0

傳遞const引用是線程無關的。看看下面簡單的代碼:

void foo(const std::shared_ptr<int>& x) { 
    sleep(100000); 
} 


void bar() { 
    //... 
    std::shared_ptr y = ...; 
    foo(y); 
} 

y想要住在酒吧,直到foo回報 - 從而確保shared_ptr仍然有效。如果foo()要創建另一個線程並將x傳遞給它,它將不得不復制它 - 這將增加引用計數器。

0

通過引用傳遞總是線程安全的,無論哪個對象被傳遞。如果它是對const的引用,它是無關緊要的。