1

我正在编写一个内容管理系统,以避免在我的游戏引擎中重复加载相同的纹理。以下是从先前加载的对象中检索内容或在没有可用对象时加载新对象的功能。

    template <class T>
    T* GetContent(const char* path) {
        // Check if it already exists, if yes return it
        for (ContentEntry& entry : m_ContentList) {
            // Same Type?
            if (strcmp(entry.Type, T::GetType()) == 0)
                // Same Path?
                if (strcmp(entry.C->GetPath(), path) == 0)
                    return (T*)entry.C;
        }

        // Since it doesn't exist, create it
        ContentEntry contentEntry (
            T::GetType(),
            (Content*)new T(path));

        // Add it to the list
        m_ContentList.push_back(contentEntry);

        // And Return it
        return (T*)contentEntry.C;
    }

这是用于存储内容条目的结构和存储它们的向量。

    struct ContentEntry {
        const char* Type;
        Content* C;

        ContentEntry(const char* type, Content* c) :
            Type(type),
            C(c)
        { }
        ~ContentEntry() {
            delete C;
        }
    };

    std::vector<ContentEntry> m_ContentList;

每当此函数尝试返回值时,应用程序就会崩溃。当我将 contentEntry 更改为一个指针(适当地更新它周围的代码)时,它会毫无问题地返回,但我必须将整个向量更改为指向 ContentEntry 指针,然后手动删除它们,如果可能的话我想避免这样做。我怎样才能使这个功能正常工作?

此外,当使用指针并单步执行 foreach 循环时,向量似乎无缘无故急剧增长,我该如何阻止这种情况发生?

编辑:现在修复了我稍后会改进的崩溃问题,但失控的向量仍然存在。

Edit2:在退出函数后,增长的向量似乎就消失了,所以我只是将某些东西标记为答案。

4

3 回答 3

2

delete从外观上看,您正在使用而不是删除看起来像字符串的内容delete[]。当然,这假设首先分配了字符串。根据您的评论,您尝试delete使用导致未定义行为的字符串文字。

也就是说,请注意,当您将对象插入向量时,您正在对对象进行切片,更重要的是,您不会获得ContentEntry成员的深层副本(这种类型缺少复制构造函数,并且可能缺少赋值运算符)。因此,在插入ContentEntrystd::vector<ContentEntry>分配的对象后,它就消失了。另一个有趣的地方是你将你的文件T*转换为Content*. 分配对象是deleted 通过指向 的指针Content。因此,要么强制转换是不必要的(希望你的类型Contentvirtual析构函数),要么事情会在那时开始变糟。

于 2013-08-14T23:49:22.033 回答
1
    // Since it doesn't exist, create it
    ContentEntry contentEntry (
        T::GetType(),
        (Content*)new T(path));

    // Add it to the list
    m_ContentList.push_back(contentEntry);

    // And Return it
    return (T*)contentEntry.C;

您的问题出在这三行中,并且ContentEntry没有复制构造函数(和复制分配)。

  • 在第一部分中,您创建一个 ContentEntry 实例
  • 然后push_back是该实例的副本。此副本将指向原始ContentEntry指向的同一 T 实例。
  • 最后,函数退出,返回指向 T 的指针。但是在出口处,您的本地副本contentEntry被销毁,这将delete返回的指针指向的 T 实例。

从本质上讲,你没有遵守三法则并因此受到惩罚。

于 2013-08-15T00:03:55.817 回答
0

您需要 ContentEntry 的复制构造函数。

于 2013-08-15T00:19:24.963 回答