在一组类中一次仅实例化一个类以节省内存

时间:2016-11-06 09:43:07

标签: c++ class

以下内容与this直接相关。我想要的是能够一次调用并且只激活一个类,以节省内存,还因为我打算稍后添加一个GUI,所以我可以通过一个来调用类下拉菜单(例如)。

我尝试制作作品,这就是出来的结果:

#include <iostream>

class Power
{
private:
    double m_x;
public:
    Power() {std::cout<<"Power\n";}
    Power(double x): m_x {x} {std::cout<<"Power("<<x<<")\n";}
    ~Power() {std::cout<<"~Power\n";}
    const double getX() const { return m_x; }
};

class Scanner
{
private:
    Power m_power;
public:
    Scanner() {std::cout<<"Scanner\n";}
    Scanner(const Power &p): m_power {p} {std::cout<<"Scanner("<<&p<<")\n";}
    void print() {std::cout<<"x="<<m_power.getX()<<'\n';}
};

class Printer
{
private:
    Power m_power;
public:
    Printer() {std::cout<<"Printer\n";}
    Printer(const Power &p): m_power {p} {std::cout<<"Printer("<<&p<<")\n";}
    void print() {std::cout<<"x="<<m_power.getX()<<'\n';}
};

class Copier // if Copier is to be used for "unification", will "public" be needed?
{
private:
    Scanner *m_s;
    Printer *m_p;
    int m_i;
public:
    Copier() {std::cout<<"Copier\n";}
    Copier(const Power &p, int i): m_i {i}
    {
        if (i)
            m_s = new Scanner(p);
        else
            m_p = new Printer(p);
        std::cout<<"Copier("<<&p<<","<<i<<")\n";
    }
    void print() { std::cout << (m_i ? m_s->getX() : m_p->getX()) << '\n'; }
};

int main(int argc, char *argv[])
{
    Scanner *s {new Scanner(Power(2.3))};
    s->print();
    Printer *p {new Printer(Power(3.14))};
    p->print();
    s->print(); // here, both *s and *p exist, both use memory
    // this comes after considering adding class Copier
    Copier *c {new Copier(Power(1.618), 0)};
    c->print();
    c = new Copier(Power(2.718), 1);
    c->print();
    return 0;
}

忽略Copier一点。事实上,我可以使用它,这就是出现的结果:

Power(2.3)
Scanner(0x7ffc80d98c10)
~Power
x=2.3
Power(3.14)
Printer(0x7ffc80d98c20)
~Power
x=3.14
x=2.3

现在(主要)问题是内存中有多个对象,*s*p,你可以看到x可以用{{1}打印出来}和3.14。如果我有超过2个类(我这样做),我可以调用每个类,每个类都会占用内存。那不是我想要的东西。

如何一次只调用一个班级而不必调用额外的重置或删除?我想为它添加另一个类,请参阅2.3。但是我不能使用Copier并且代码中的解决方案不仅非常难看,而且甚至不起作用。另外,它会像疯子一样召唤建设者。

我尝试在一个简单的函数中使用std::unique_ptr std::unique_ptr(需要std::make_unique,而我宁愿保留更大的安全边距,但我也可以忍受它,太)。它也不起作用,因为它指向c++14(如果我将Power称为z->print()):

'class Power' has no member 'print'

我不知道如何做到这一点。简而言之,类std::unique_ptr<Power> call(const Power &p, const int &i) { if (i) return std::make_unique<Printer>(p); else return std::make_unique<Scanner>(p); } Scanner以及任何其他存在的类都是专用类,它们只执行一项任务,在计算方式上是唯一的,并且它们都使用了一些常见的变量。 Printer(除了他们自己的)。我不认为将公共变量移动到每个类是非常有效的,因为它们只会膨胀代码,而且,据我所知,“如果你可以使用存储类而不是一遍又一遍地重复相同的变量,用它“(不是我的话,这是真的吗?)。然后,我希望能够实例化这些类,但一次只有一个活动,以节省内存。

作为一个例子,假设一个类生成1mil值的数组,然后另一个生成1mil不同的值,依此类推。想象一下,在内存中使用该数组的次数与实例化的类一样多。我不希望这样。 Power的目的是一次只调用一个类(基于条件)。任务完成?打电话给另一个,但忘记之前做过的任何其他事情,重新开始。所有这些只能通过一个小部件调用,例如从列表中选择,单击&amp; go,稍后将添加。

这是一个愚蠢的错误,我忘了在复制粘贴后删除Copier。我现在也尝试了代码(使用public ...),它编译,但仍然不起作用,Copier保持为空,即使有两个m_x和{{的非常难看的解决方案1}}指针作为Scanner内的成员变量。

好吧,经过一些尝试,我无法做出我想要的东西,所以我想回到我原来的想法,即使它意味着继承。所以我提出了这段代码,在那里我更改了名称以使其更有意义(?):

Printer

现在,这有效,但我有一种感觉,我在坏代码示例上设置了新记录。请不要为此抨击我,而是指出所有的错误,或者你将如何做到这一点以达到同样的结果。尽管如此,即使它看起来像我想要的那样工作,它仍然会调用所有分支上的所有构造函数,而不仅仅是所需的构造函数。我意识到(道歉)我忘了说Copier,这里也负责#include <iostream> class Garage { protected: double m_x; // gas, tires, etc, that all cars use, reside in the Garage public: Garage() {std::cout<<"Garage\n";} virtual ~Garage() {std::cout<<"~Garage\n";} }; class Audi: virtual public Garage { public: Audi() {std::cout<<"Audi\n";} void f(const double &x) { m_x=x; std::cout<<"Audi::f("<<x<<")\n";} }; class Bmw: virtual public Garage { public: Bmw() {std::cout<<"Bmw\n";} void f(const double &x) { m_x=x; std::cout<<"Bmw::f("<<x<<")\n";} }; class Driver: public Audi, public Bmw { private: double m_y; // report of driving, based on m_x public: Driver() {std::cout<<"Driver\n";} Driver(const double &x, int i) { if (i) Bmw::f(x); else Audi::f(x); m_y = -m_x; std::cout<<"Driver("<<x<<","<<i<<")\n"; } void print() { std::cout << "x=" << m_x << ", y=" << m_y << '\n'; } }; int main(int argc, char *argv[]) { Driver *d {new Driver(1.618, 0)}; d->print(); d = new Driver(0.618, 1); d->print(); // even iteration works now delete d; d = nullptr; // to be sure it's dead(?) for (int i=0; i<2; ++i) { d = new Driver(3.14, i); d->print(); } return 0; } 进一步使用Driver(这就是为什么代码有点不同)。< / p>

我想指出的是,只要达到我的目的,我就不会保留这些代码或任何其他代码,我愿意改变和适应。但由于我是一个初学者,我不能制作太多的组合,所以我只留下了我试图让自己理解的任何结果。上面的程序,就像运行时一样,提供我想要的东西,甚至可以制作一个循环,这将让我在GUI中更容易使用它,以后。这些名称在组成中最有意义,m_x 有一个 m_y,这就是我尝试过的,但我无法获得我的意思通缉。因此,即使这使用了继承并且Garage 是-a Bmw也没有意义,我保留了名称来建议我的初始试用组合。我发布这个的主要原因是为了展示我希望该程序做什么。 Audi中发生的事情将在GUI中使用,我在考虑Qt,因为我希望在所有3个主要操作系统上运行。因此,有可能一次调用一辆汽车,使用它,并且能够存储以前的信息,而不会在内存中存在过时的对象,只有Garage * nr_of_cars,这将使它更容易使用。

2 个答案:

答案 0 :(得分:1)

这是一种方法。

{ // scope begins
   Printer p; // note, no pointers
   p.print(); 
} // scope ends, p is gone

这里我们有一个出现的对象,一次做一次,然后消失。

这是另一个

boost::variant<Printer,Scaner,Copier> psc(Printer());
psc.get<Printer>().print();
psc = Scaner(); // the printer is gone

答案 1 :(得分:0)

使用一些std::unique_ptr构造函数:

std::unique_ptr<Power> 
call(const Power &p, const int &i) {
  if (i)
    return std::unique_ptr<Power>(new Printer(p));
  else
    return std::unique_ptr<Power>(new Scanner(p));
}

也许你真正想要的是tagged union。关注rule of five。请参阅this获取灵感。