簡體   English   中英

存儲和使用 smart_ptr 地址

[英]Storing and using smart_ptr address

我正在嘗試將shared_ptr傳遞給周圍的 object,它可能是也可能不是 null:

#include <iostream>
#include <memory>

struct MyObject {
  int i = 0;
  MyObject(const int i_) : i(i_) {}
};

struct Command {
  std::shared_ptr<MyObject> cmdObj;

  Command(std::shared_ptr<MyObject>& obj) : cmdObj(obj) {
    std::cout << "Store and use this address: " << &obj << std::endl;  // [1]
  }

  void execute() {
    if (cmdObj == nullptr) {
      cmdObj = std::make_shared<MyObject>(42);
    } else {
      cmdObj->i = 7;
    }
  }
};

struct CommandManager {
  std::shared_ptr<MyObject> globalObj;  // [1]

  CommandManager() { globalObj = nullptr; }

  void runCommand() {
    Command cmd(globalObj);
    cmd.execute();
  }
};

int main() {
  CommandManager cm;
  std::cout << "cm.globalObj address: " << &cm.globalObj << std::endl;  // [1]
  cm.runCommand();
  if (cm.globalObj == nullptr) {
    std::cout << "globalObj is null" << std::endl;
  } else {
    std::cout << "globalObj is " << cm.globalObj->i << std::endl;
  }
}

如您所見,我正在嘗試從Command中操縱或創建globalObj 但是,盡管在構造函數 ( [1] ) 中傳遞了地址,但我沒有正確存儲它,因此新的 object 在CommandManager中可用。

我該怎么做才能正確存儲和使用shared_ptr<MyObject>的地址?

先感謝您。

要存儲地址,您需要一個指針。 在這種情況下,指向 std::shared_ptr 的指針。

struct Command {
  std::shared_ptr<MyObject>* cmdObj;

  Command(std::shared_ptr<MyObject>& obj) : cmdObj(&obj) {
    std::cout << "Store and use this address: " << &obj << std::endl;  // [1]
  }

  void execute() {
    if (*cmdObj == nullptr) {
      *cmdObj = std::make_shared<MyObject>(42);
    } else {
      (*cmdObj)->i = 7;
    }
  }
};

演示

您也可以在此處使用引用,因為您需要將某些內容傳遞給Command的構造函數,並且您不會遇到懸空引用問題,除非您在使用前一個選項時遇到懸空指針問題。

struct Command {
  std::shared_ptr<MyObject>& cmdObj;

  Command(std::shared_ptr<MyObject>& obj) : cmdObj(obj) {
    std::cout << "Store and use this address: " << &obj << std::endl;  // [1]
  }

  void execute() {
    if (cmdObj == nullptr) {
      cmdObj = std::make_shared<MyObject>(42);
    } else {
      cmdObj->i = 7;
    }
  }
};

演示

但是,我不確定您是否真的想要一個std::shared_ptr開頭。 一個簡單的變量也可以。

struct Command {
  MyObject* cmdObj;

  Command(MyObject* obj) : cmdObj(obj) {
    std::cout << "Store and use this address: " << obj << std::endl;  // [1]
  }

  void execute() {
      cmdObj->i = 7;
  }
};

struct CommandManager {
  MyObject globalObj = 42;  // [1]

  void runCommand() {
    Command cmd(&globalObj);
    cmd.execute();
  }
};

int main() {
  CommandManager cm;
  std::cout << "cm.globalObj address: " << &cm.globalObj << std::endl;  // [1]
  cm.runCommand();
  std::cout << "globalObj is " << cm.globalObj.i << std::endl;
}

演示

如果您的初衷是通過std::shared_ptr共享MyObject object,那么您需要先創建該 object,然后才能共享它。

struct Command {
  std::shared_ptr<MyObject> cmdObj;

  Command(std::shared_ptr<MyObject>& obj) : cmdObj(obj) {
  }

  void execute() {
      cmdObj->i = 7;
  }
};

struct CommandManager {
  std::shared_ptr<MyObject> globalObj;  // [1]

  CommandManager() { globalObj = std::make_shared<MyObject>(42); }

  void runCommand() {
    Command cmd(globalObj);
    cmd.execute();
  }
};

演示

或者您可以在Command中創建它,然后與CommandManager共享。

struct Command {
  std::shared_ptr<MyObject> cmdObj;

  Command(std::shared_ptr<MyObject>& obj) {
    if (obj == nullptr) {
        obj = std::make_shared<MyObject>(42);
    }
    cmdObj = obj;
  }

  void execute() {
    cmdObj->i = 7;
  }
};

演示

或者,您可以創建一個std::unique_ptr並共享它,然后在需要時在Command中創建MyObject object。

struct Command {
  std::shared_ptr<std::unique_ptr<MyObject>> cmdObj;

  Command(std::shared_ptr<std::unique_ptr<MyObject>> obj) : cmdObj(obj) {
  }

  void execute() {
    if (*cmdObj == nullptr) {
      *cmdObj = std::make_unique<MyObject>(42);
    } else {
      (*cmdObj)->i = 7;
    }
  }
};

struct CommandManager {
  std::shared_ptr<std::unique_ptr<MyObject>> globalObj;  // [1]

  CommandManager() { globalObj = std::make_shared<std::unique_ptr<MyObject>>(nullptr); }

  void runCommand() {
    Command cmd(globalObj);
    cmd.execute();
  }
};

演示

注意:引用不是地址,盡管使用與地址運算符相同的&字符。 我假設您是在談論參考,而不是地址。

您將globalObj引用傳遞給構造函數,但是唯一的引用是形式參數obj

您打印obj的地址並驗證它是否與預期的globalObj地址相同。 但是cmdObj不是obj

cmdObj是 object,不是參考。 初始化它將創建您初始化它的任何內容的副本,與原始文件完全斷開鏈接。 它的地址是不同的,你可以打印出來自己看看。

更改cmdObj (副本)不會以任何方式、形狀或形式影響globalObj (原始)。

if (cmdObj == nullptr) {  
  // Before the assignment, globalObj was nullptr.
  cmdObj = std::make_shared<MyObject>(42);
  // And it still is after the assignment to cmdObj.

您也可以將cmdObj作為參考:

Mystd::shared_ptr<MyObject>Object*& cmdObj;

這可能會產生您想要的效果。

請注意,我不是在談論任何這些智能指針指向的對象。 只是指針本身。

顯示shared_ptr生命周期和它們指向的 object 生命周期之間差異的最小程序。

#include <iostream>
#include <memory>

int main() {

  // Create an integer, give shared ownership to sp_1
  std::shared_ptr<int> sp_1 = std::make_shared<int>(2);

  // sp_2 points to same integer now, so sp_2.get() == sp_1.get().
  // Reference count is increased to 2.
  // Note that sp_1 and sp_2 are still different objects, i.e. &sp_2 != &sp_1 
  std::shared_ptr<int> sp_2 = sp_1;

  // Value of int is changed (both sp_1 and sp_2 point to it)
  *sp_2 = 4;

  // Replace shared_ptr object sp_2. It now points to another integer object.
  // sp_1 is not affected by it, the reference count to the first integer is back down to 1.
  sp_2 = std::make_shared<int>(6);

  std::cout << *sp_1 << " is still 4!" << std::endl;
  std::cout << *sp_2 << " is 6!" << std::endl;

  // "Destroy" first integer object
  sp_1.reset();

  // This is perfectly valid since sp_2 is pointing to a different integer
  *sp_2 = 8;
  std::cout << *sp_2 << " is 8!" << std::endl;

  return 0;
}

在這里運行: https://godbolt.org/z/qMKvzzbWE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM