2014-12-19 87 views
1

我有一個函數需要返回另一個類的新對象,所以我認爲我需要將它的返回對象保存在一個共享指針中。像這樣返回一個shared_ptr

內部類X;

Y* func(param) 
{ 
    return new Y(param); 
} 

我已經嘗試過改變成

std::shared_ptr<Y> func(param) 
{ 
    std::shared_ptr<Y> y(new Y(param)); 
    return y; 
} 

我不想返回本地對象,所以我應該怎麼辦?

+1

不必返回本地對象,你返回一個副本。它也是'std :: shared_ptr'。使用'std :: make_shared'。 – user657267 2014-12-19 07:57:55

+1

將'share_ptr'改爲'shared_ptr'後,它應該可以工作。 – 2014-12-19 07:58:15

+2

在任何情況下,您都返回一個本地對象,在這兩種情況下返回的值都是*拷貝*。在第一個指針是副本,並在第二個對象被複制。另外,也許不相關,但是你不應該將'std :: shared_ptr'和'std :: unique_ptr'看作*指針*,而應該從大多數情況下來看待它們。 – 2014-12-19 08:00:10

回答

3

我建議你有std::shared_ptr的返回類型和return std::make_shared<Y>()轉移所有權。

這裏是一個工作的例子,可以幫助你:

#include <memory> 
#include <iostream> 
#include <string> 

class Y { 
public: 
    Y(const std::string& n) 
    : name{n} {} 

    std::string name; 
}; 

std::shared_ptr<Y> func() 
{ 
    return std::make_shared<Y>("new class"); 
} 

int main() 
{ 
    std::shared_ptr<Y> p_class = func(); 
    std::cout << p_class->name; 
    // outputs: "new class" 

    return 0; 
} 
2

您返回一個堆分配對象,這意味着您轉移所有權。我會建議你使用std::unique_ptr返回類型

std::unique_ptr<Y> func(param) 
{ 
    return std::unique_ptr<Y>(new Y(param)); 
} 

更妙的是使用std :: make_unique(如果它已經可用,否則寫你自己的),或者 - 如果你使用的shared_ptr - 的std :: make_shared。對於異常安全以及shared_ptr更高效的情況更好。

std::unique_ptr<Y> func(param) 
{ 
    return make_unique<Y>(param); 
} 

std::shared_ptr<Y> func(param) 
{ 
    return std::shared_ptr<Y>(param); 
} 

並注意您的func複製了參數。您可能想要使用轉發來避免這種情況。

template<class T, class U> 
std::unique_ptr<T> make_unique1(U&& u) 
{ 
    return std::unique_ptr<T>(new T(std::forward<U>(u))); 
} 

template<class T, class... U> 
std::unique_ptr<T> make_unique(U&&... u) 
{ 
    return std::unique_ptr<T>(new T(std::forward<U>(u)...)); 
} 
0

除了我的回答暗示std::unique_ptr,我想指出,這是沒有必要在堆上創建一個對象從返回它功能。您可以通過值只返回新的對象:

Y func(param) 
{ 
    Y result(param); 
    return result; 
} 

這將(並一直)工作,如果Y是可複製。如果該類不可複製,則它將不起作用,如果它可行,則可能涉及複製該對象。

雖然大多數編譯器確實消除了多年的副本,但現在如果返回一個未命名的臨時對象,現在必須由標準C++17強制執行。這意味着,下面的代碼將編譯並返回,即使你有一個不可複製和不可移動的對象的新對象:

class Y { 
    public: 
    Y(int i): value(i) {} 
    Y(Y const&) = delete; 
    Y(Y&&) = delete; 
    Y& operator=(Y const&) = delete; 
    Y& operator=(Y&&) = delete; 

    int value; 
}; 

Y foo(int i) { 
    return Y(i); 
} 

void bar { 
    Y y = foo(42); 
} 
相關問題