在C++中根据需要为数据结构分配空间



我有以下形式的数据结构:

class A{
    unsigned t;
    bool isPresent;
    map<unsigned,unsigned> isPresentA;
    map<unsigned,unsigned> isPresentB; 
};
int main(int argc, char** argv) {
    A a;
    cout<<"size of map="<<sizeof(a)<<"n";
    return 0;
}

现在,当a.isPresent为真时,则只有我在a.isPresentAa.isPresentB中存储值。当a.isPresent为false时,则映射的a.isPresentAa.isPresentB为空。然而,我看到尽管我没有在a.isPresentAa.isPresentB中存储值,但它的大小仍然是104。C++中是否有某种方法可以使我仅在需要的基础上(即当a.isPresent为真时)为a.isPresentAa.isPresentB分配空间,而不是显式地为它们分配存储空间。

我正在存储数百万个A类对象,因此A类的大小是我关心的问题

我使用的是gcc版本:gcc(Ubuntu/Linaro 4.6.4-6ubuntu2)4.6.4

创建类A的实例时,会自动分配这两个映射。为了应对这种情况,你可以用它们来制作指针:

class A{
    unsigned t;
    bool isPresent;
    map<unsigned,unsigned>* isPresentA;
    map<unsigned,unsigned>* isPresentB; 
};

但是,您现在需要自己分配(并删除!)它们!一个更安全的选择是使用std::shared_ptr:

class A{
    unsigned t;
    bool isPresent;
    std::shared_ptr<map<unsigned,unsigned>> isPresentA;
    std::shared_ptr<map<unsigned,unsigned>> isPresentB; 
};

您仍然需要初始化它们,但至少您不必担心删除它们。您应该在类中添加一个构造函数或初始值设定项函数来实现这一点:

class A{
    A(bool is_present) {
        isPresent = is_present;
        if (isPresent) {
            isPresentA = std::make_shared<map<unsigned int, unsigned int>>();
            isPresentB = std::make_shared<map<unsigned int, unsigned int>>();
        }
    }
    unsigned t;
    bool isPresent;
    std::shared_ptr<map<unsigned,unsigned>> isPresentA;
    std::shared_ptr<map<unsigned,unsigned>> isPresentB; 
};

通过使用unique_ptr:,您可以在不使类复杂化的情况下实现所需内容

#include <map>
#include <memory>
class A {
    unsigned t;
    unique_ptr<map<unsigned, unsigned>> isPresentA;
    unique_ptr<map<unsigned, unsigned>> isPresentB;
};

您可以直接使用isPresentA或B:来检查是否存在

if (a.isPresentA) {
}

或者将其封装到某个类方法alla bool isPresent();

一个更精细的版本可能看起来像这样:

#include <memory>
#include <map>
using namespace std;

class A {
    struct OptinalParts {
        map<unsigned, unsigned> a;
        map<unsigned, unsigned> b;
    };
    unsigned t;
    unique_ptr<OptinalParts> optional;
public:
    A() :t(0),optional(nullptr){};
    A(bool initState):t(0) {
        makePresent(initState);
    }
    bool isPresent() {
        return (bool)optional;
    }
    void makePresent(bool set) {
        if (set && !isPresent())  {             
            optional.reset(new OptinalParts);                   
        }
        else {
            optional.reset(nullptr); 
        }
    }
    /*
    * accessors
    */
};

您可能需要用NULL 替换任何出现的nullptr

最新更新