2024年11月26日 星期二

在function裡動態新增物件時,如何用make_shared讓新增的物件不會在離開function時被釋放

當你在一個函數內動態創建物件時,使用 std::make_shared 是一個非常合適的選擇,因為它會返回一個 std::shared_ptr,這樣你就可以確保物件的生命週期在超出該函數作用域後仍然有效,並且直到不再有 shared_ptr 引用它時才會被釋放。

如果你希望確保在函數離開時物件不會被釋放,可以將該 std::shared_ptr 返回,或者將其存儲在函數外部的變量中。

std::make_shared 創建物件並確保其不會在函數結束時被釋放的方式:

1. 返回 shared_ptr 給外部

std::shared_ptr 返回給外部,這樣外部可以繼續持有該物件的引用,直到不再需要它時才會釋放。

#include <memory> // for std::make_shared
#include <iostream> class MyClass { public: void sayHello() { std::cout << "Hello, World!" << std::endl; } }; std::shared_ptr<MyClass> createObject() { // 使用 make_shared 動態創建物件 auto myObject = std::make_shared<MyClass>(); // 返回 shared_ptr,物件會繼續存在直到所有 shared_ptr 被銷毀 return myObject; } int main() { // 在 main 函數中接收返回的 shared_ptr std::shared_ptr<MyClass> myObject = createObject(); // 可以繼續使用 myObject myObject->sayHello(); // 當 myObject 不再被引用時,MyClass 物件才會被釋放 return 0; }

解釋:

  1. std::make_shared<MyClass>():在 createObject 函數內,使用 std::make_shared 創建一個 MyClass 物件,並將它包裝在 std::shared_ptr 中。

  2. 返回 shared_ptr:將創建的 std::shared_ptr 返回給 main 函數。當 main 函數接收到返回值後,myObject 將繼續保持對 MyClass 物件的引用。

  3. 物件不會被釋放:只要 main 函數中的 myObject 還持有 shared_ptr,該物件就不會被釋放。只有當 main 中的 shared_ptr 被銷毀(例如,當函數結束時)或者不再引用該物件時,MyClass 物件才會被釋放。

2. shared_ptr 存儲在外部變量中

如果你希望在函數外部持有這個物件,可以將 shared_ptr 儲存在函數外部的變量中,而不是返回。

#include <memory> // for std::make_shared
#include <iostream> class MyClass { public: void sayHello() { std::cout << "Hello, World!" << std::endl; } }; void createObject(std::shared_ptr<MyClass>& outObject) { // 使用 make_shared 動態創建物件並將 shared_ptr 傳遞給外部 outObject = std::make_shared<MyClass>(); } int main() { std::shared_ptr<MyClass> myObject; // 呼叫 createObject 並將 shared_ptr 傳入 createObject(myObject); // 現在 myObject 持有這個物件,直到它不再被引用時才會釋放 myObject->sayHello(); // 當 myObject 不再被引用時,MyClass 物件才會被釋放 return 0; }

解釋:

  1. shared_ptr 引用傳遞給外部:在這個版本中,createObject 函數通過引用參數 outObject 將創建的 shared_ptr 傳遞給外部。

  2. 外部持有 shared_ptrmain 函數接收 shared_ptr 並可以繼續使用這個物件。

  3. 物件生命週期管理:這樣,當 main 中的 shared_ptr 被銷毀或不再引用物件時,MyClass 物件才會被釋放。

沒有留言:

張貼留言