【问题标题】:Correct way to store objects in another object in C++?在 C++ 中将对象存储在另一个对象中的正确方法?
【发布时间】:2014-12-12 14:30:23
【问题描述】:

我有 3 个对象,我们称它们为 MainManagerItemManager 需要有一个 Items 数组。这些ItemsMain 对象添加到Manager

我想知道我应该如何将 Items 传递给 Manager 以使它们即使在 Main() 函数范围之外仍然存在,但同时能够在Manager 被销毁。

注意 Item,在Manager 内部,必须是指针,因为我需要检查 NULL 项

到目前为止,我有这样的东西(不是实际的代码):

Main
{
    Manager* Man;
    Main()
    {
        Man = new Manager(/**/);   //i use a pointer because i need this object to persist;
        Item* it = new Item(/**/);
        Man->AddItem(it);
    }
    ~Main()
    {
        delete(Man);
    }
}

Manager
{
    Item* ItemArchive[15];
    void AddItem(Item* item)
    {
        ItemArchive[index] = item;
    }
    ~Manager()
    {
        for(int i=0;i<archiveLength;i++)
            delete(ItemArchive[i]);    //Here i get a runtime error,most probably an 
                                       //access violation,can't be more specific
                                       //because Unreal Engine doesn't give me that info
    }
}
Item
{
    //just a basic object
}

所以我的问题是,如何在Main 中创建对象,然后在Manager 中使用和删除它们?

【问题讨论】:

  • 一般来说,我不会命名函数或其他实体 Main() 或 main()。我也会避免将可执行文件命名为“test”或“ls”。
  • 一般来说,像“删除管理器时删除项目”这样的清理属于析构函数。如果您复制指针,只需确保它们指向的对象不会超出范围,例如通过使用新的或现代的 unique/shared_ptr 模板;另一方面,确保在经理删除它们后不再使用它们(即经理拥有所有权)。后者在复杂程序中可能不那么简单,但现代 C++ 智能指针工具可以提供帮助。
  • “我使用指针是因为我需要这个对象来持久化” - 持久化到什么程度?无论如何,它都会在析构函数中被破坏。我不明白你为什么不能让Manager 成为会员。
  • @giorgim 感谢您的链接

标签: c++ object segmentation-fault new-operator delete-operator


【解决方案1】:

考虑使用std::unique_ptr&lt;Item&gt; 并将所有权从Main 传递给Manager

#include <vector>
#include <memory>

class Item {};

class Manager {
    std::vector<std::unique_ptr<Item>> item_archive;
  public:
    void addItem(std::unique_ptr<Item> item){
        item_archive.push_back(std::move(item));
    }
};

int main() {
    Manager manager;
    auto item = std::make_unique<Item>();  // C++14
    //auto item = std::unique_ptr<Item>(new Item);  // C++11
    manager.addItem(std::move(item));
}

这样,当Manager被销毁时,项目将被删除,而无需编写析构函数。

我建议使用std::vector 而不是数组,因为它简化了项目存档的管理。

由于您尚未发布实际代码,因此无法确定究竟是什么导致了运行时错误,但使用 std::vectorstd::unique_ptr 很可能会解决它。

Live demo

【讨论】:

  • 感谢您的示例,我认为您的帖子让我朝着正确的方向前进。现在我遇到了一些错误,例如“尝试引用已删除的函数”,但我正在尝试解决它。​​跨度>
  • 要使用std::unique_ptr,您需要对move semantics 有一些了解,因为std::unique_ptr 是可移动的,但不可复制(因此会出现错误)。但这是值得的。
【解决方案2】:

没有理由不允许Manager 删除Items。您的错误可能是您超出了ItemArchive 数组或两次删除对象?很难说,因为你已经重写了问题的代码。

我想说尝试使用一个可以调试的系统,然后你会学得更快!调试器真是太棒了。

【讨论】:

  • 不,这段代码不好,甚至都不正确。你不能说在这个例子中实际工作的是什么。显然AddItem 不会添加超过一项,~Manager 会删除未初始化的值。
  • 如果archiveLength 正确,它只会删除单个添加的值。就他的查询而言,这“很好”,即“另一个类可以删除它没有创建的对象”。这就是为什么我用冒号扩展了“好”的含义。学着阅读。我已经编辑了我的答案,所以像你这样的人不必担心语法等问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多