存储大型相似物体的更好方法

时间:2013-03-17 17:34:06

标签: c++ class vector

所以我有一个'大'班A,另一个班B,其中包含至少100个A对象的向量。将B类中的所有对象存储为vector<A>似乎不是一个好主意,因为可以重复使用大量信息。

我正在考虑在课程B中设置一个模板,该模板包含A的所有类似属性,然后为其创建vector<A*>。但这使他们都一样......

那么有没有一种存储类的类似变量的方法,以便只需要多次存储少量差异?

最小工作示例

#include <iostream>

// suppose an int is big:
struct A { // create struct which holds 3 ints
    A() : a(0),b(0),c(0) {} //ctor

    void print() { // print all variables
        cout << a << ", " << b << ", " << c << endl;
    }
    int a,b,c;
};

class B { // create object that holds a vector of A
public:
    B(int vectorSize) {
        vector_A.resize(vectorSize);
        vector_ptr_A.resize(vectorSize);
    }

    void initValues() {
        ///////////////////////////////////////
        // METHOD 1
        vector_A.resize(vectorSize); // resize 
        for (int i=0; i<vector_A.size(); ++i) {
            vector_A[i].a = rand() % 100; // randomize A::a
            vector_A[i].b = 5;            // only B wants A::b to be 5
            vector_A[i].c = 10;           // only B wants A::c to be 10
        }
        ///////////////////////////////////////

        ///////////////////////////////////////
        // METHOD 2
        A_template.b = 5;  // only B wants A::b to be 5
        A_template.c = 10; // only B wants A::c to be 10
        vector_ptr_A.resize(vectorSize,&A_template); // point to template
        for (int i=0; i<vector_ptr_A.size(); ++i) {
            vector_A[i].a = rand() % 100; // randomize A::a
        }
        ///////////////////////////////////////
    }

    void print1() { // prints vector_A[i]
        for (int i = 0; i < vector_A.size(); ++i) {
            vector_A[i].print();
        }
    }
        void print2() { // prints vector_ptr_A[i]
        for (int i=0; i < vector_ptr_A.size(); ++i) {
            vector_ptr_A[i]->print();
        }
    }

    // method 1
    vector<A> vector_A; // a big, big vector

    // method 2
    A A_template;
    vector<A*> vector_ptr_A; // all the same
};

int main() {
    srand( time(NULL) );
    B b(10);
    b.initValues();

    cout << "METHOD 1\n";
    b.print1();             // as desired, but inefficient
    cout << "\nMETHOD 2\n";
    b.print2();             // all the same output
}

修改

一些澄清,因为最小的工作示例有点令人困惑。我现在也对它进行了调整以使其更加清晰。

班级A的成员应由B和用户设置。例如,用户将为向量的每个元素定义A::a(由随机表示),而另外2个(A::bA::c)由B定义。类A不是仅由B使用的类,而是由用户或任何其他类使用的类。

所以基本上我要求一个方法,所以我不必为向量的每个元素设置A::bA::c,但只需要一次。 A::a对于我应该设置的每个元素都是不同的。

要找到我想要的原因:类A在我的程序中是Sprite类,而B必须能够将精灵打印为tile并命名为TileMapTileMap中的向量因此可以在窗口上绘制很多Sprite,但是对于所有这些图块(纹理图块大小,绘图图块大小,纹理文件等)我不想为每个瓷砖设置所有这些变量。我想创建一些可用于向量中的每个Sprite的模板。这种方式不仅更容易,占用空间更少,而且更安全:我知道所有这些值都是完全相同的。

3 个答案:

答案 0 :(得分:1)

需要做一些澄清,但我会理解你的问题。

struct Common_A_Members
{
  int x;
  double y;
};

struct Uncommon_A_Members
{
  unsigned int this_member_changes;
};

struct A : public Common_A_Members, public Uncommon_A_Members
{
  A(const Common_A_Members& c, const Uncommon_A_Members& d)
  : Common_A_Members(c), Uncommon_A_Members(d)
  { ; }
};


struct B
{
  Common_A_Members a_common;
  std::vector<Uncommon_A_Members> a_uncommon;
};

在上面的示例中,概念类分为两部分,一部分包含不更改的值(Common_A_Members)和更改的值(Uncommon_A_Members)。这允许B拥有常量数据的一个成员和changing数据的向量。 A概念类有一个构造函数,它结合了常量数据和不断变化的数据。

B中的两个成员是一组。对于具有不同常量值的概念类,需要复制或重复该集合。

该理论是从不断变化的数据中分解出恒定的数据。

答案 1 :(得分:1)

如果变量b,c对于A的所有实例始终相同 - 在A中将它们设为静态。

如果变量b,c对于存储在B的一个实例中的A的实例集是相同的,则考虑将b,c放在B中。

如果变量b,c仅对某些A组相同,则考虑因子out b,c为它自己的“config”类C,并将智能指针存储到C中的A.这假定b,c足够大,或由足够的实例共享,以使额外的管理变得有价值。

顺便说一下,你确定你的print2()函数应该使用vector_ptr_A [0]而不是vector_ptr_A [i]吗? (如果可以,我会在评论中问过这个问题。)

编辑:第三个选项的参考版本:

class A_Config // stores common parts of A
{
public:
  A_Config(int a, int b) : m_a(a), m_b(b) {}
private:
  int m_a;
  int m_b;
};

class A // store parts changing for each instance and a reference to the common parts
{
public:
  A(int changing, A_Config& shared) : m_changing(changing), m_shared(shared) {}
private:
  int m_changing;
  A_Config& m_shared;
};

class B
{
public:
  B(int a, int b) : conf(a,b) {} // the common parts of A initialized 
                                 // only once when B is created

  void add_A(int changing) // add the changing parts when A is added
  {
    v.push_back( A(changing, conf) );
  }

private:
  A_Config conf;
  vector<A> v;
};

答案 2 :(得分:0)

另一种方式:

std::vector <std::reference_wrapper<A>> vector_ref_A;

示例:

A a, b, c;

std::vector < std::reference_wrapper < A >> vector_ref_A = {a, b, c};

for (int i = 0; i < vector_ref_A.size(); ++i) {
    vector_ref_A[i].get().randomize();
}

for (int i = 0; i < vector_ref_A.size(); ++i) {
    vector_ref_A[i].get().print();
}