2016-05-10 33 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的引用,它是无关紧要的。