2017-03-17 77 views
2

我想傳遞一個指向一個函數的堆棧變量(我不控制),只需要一個boost::shared_ptr提升make_shared沒有模板參數

根據this answer,使用boost::make_shared是要走的路。爲了測試這個功能,我寫了這個:

#include <iostream> 
#include <boost/shared_ptr.hpp> 
#include <boost/make_shared.hpp> 

int main(int argc, char const *argv[]) 
{ 
    int i = 10; 
    boost::shared_ptr<int> int_ptr = boost::make_shared(i); // doesn't work 
    some_function(int_ptr); // this function takes only shared_ptr 
    return 0; 
} 

但它引發以下錯誤:如果我添加模板參數,像這樣它的工作原理,但究竟是什麼原因

error: no matching function for call to ‘make_shared(int&)’ 
boost::shared_ptr<int> int_ptr = boost::make_shared(i); 
                ^

boost::shared_ptr<int> int_ptr = boost::make_shared<int>(i); 

謝謝!

+4

問問自己,如果你給它一個'int',函數應該使用什麼類型的共享指針。它如何知道你想要一個'shared_ptr '而不是'shared_ptr >',它也可以由'int'構造。 – NathanOliver

+0

請注意,模板參數推導不能包含有關結果將分配給的類型的信息。 'boost :: shared_ptr int_ptr ='部分不能被考慮來確定適當的模板參數。 –

+2

當一個'shared_ptr'指向堆棧分配的內存時,如果它試圖刪除那個內存,將會是災難性的。 「我」是否需要通過指針來修改,還是需要「我」的副本? – chris

回答

3

鑑於boost::make_shared<T>模板:

namespace boost { 
    template<typename T, typename Arg1> 
     shared_ptr<T> make_shared(Arg1 const & arg1); 
} 

的模板機制可以推斷參數arg1的類型。因爲它「看到」參數i(它是int)的類型。但是,它不能推斷返回類型T。它不知道類型的boost::shared_ptr<T>您將分配到的T(也就是沒有辦法知道的int_ptr類型。)

boost::shared_ptr<T>使用不同類型的參數(Arg1)和回報(T),讓你從不同於指針類型的參數構建共享指針。例如,doubleint

double d = 10.0; 
std::shared_ptr<int> int_ptr = std::make_shared<int>(d); 

如果你想建立共享指針,其類型是一樣的說法,你可以寫一個包裝:

template<typename T> 
boost::shared_ptr<T> my_make_shared(T const & arg) { 
    return boost::make_shared<T>(arg); 
} 

但是記住,雖然這個工程:

int i = 10.0; 
std::shared_ptr<int> int_ptr = my_make_shared(i); // OK 

的隱式類型轉換並不:

double d = 10.0; 
std::shared_ptr<int> int_ptr = my_make_shared(d); // ERROR 

希望它有幫助!

+0

指向'double'的'shared_ptr '是什麼意思? – simplename

+1

其實你沒有'shared_ptr '指向'double'。但在'make_shared '爲'int'分配內存之後,它用'double'的值初始化內存。 –

0

雖然Guilherme Ferreira的答案闡述了模板論證扣除(在這方面是正確的),我相信這不是你正在尋找的答案。

I'm trying to pass a pointer to a stack variable to a function (I don't control) that only takes a boost::shared_ptr.

shared_ptr表示對指出對象的共享所有權。如果您試圖調用的函數將指針保存在其某些數據結構(如容器)中,然後返回,那麼只要堆棧中的值被銷燬,指針就會變成懸掛的,儘管shared_ptr仍然存在一個參考。爲了做你想做的事情,你必須確保函數不會將指針保存到任何地方,並且只能在這個調用中使用它。

如果滿足此條件,您可以創建一個指向堆棧值的shared_ptr,但不能爲此使用make_sharedmake_shared在堆上分配一個新對象以及一個引用計數器,並使用傳遞給該函數調用的參數對其進行初始化。返回的shared_ptr指向該新對象,而不是指向堆棧上的對象。

void foo() 
{ 
    int n = 10; 
    boost::shared_ptr<int> pn = boost::make_shared<int>(n); 

    assert(*pn == 10); // succeeds 
    assert(pn.get() == &n); // fails 

    bar(pn); 
} 

這意味着修改bar使得到指定int不會反映在n

爲了創建一個shared_ptr到一個現有的對象,你必須直接使用它的構造函數。另外,由於對象的生命週期由堆棧控制,因此必須禁止shared_ptr銷燬該對象。這可以通過在shared_ptr構造上指定無操作刪除器來完成。

void foo() 
{ 
    int n = 10; 
    boost::shared_ptr<int> pn(&n, boost::null_deleter()); 

    assert(*pn == 10); // succeeds 
    assert(pn.get() == &n); // succeeds 

    bar(pn); 
} 

但是請注意,此代碼仍然分配堆內存引用計數器shared_ptr用途,這樣你就不會贏得任何性能。