一次只实例化一组类中的一个类,以节省内存

Instantiate only one class at a time, out of a group of classes, to save memory

本文关键字:一个 内存 节省 一组 一次 实例化      更新时间:2023-10-16

以下内容与此直接相关。我想要的是一次只能调用和激活一个类,以节省内存,但也因为我计划在以后添加GUI,所以我将能够通过下拉菜单(例如)调用类。

我试着做合成,结果是这样的:

#include <iostream>
class Power
{
private:
    double m_x;
public:
    Power() {std::cout<<"Powern";}
    Power(double x): m_x {x} {std::cout<<"Power("<<x<<")n";}
    ~Power() {std::cout<<"~Powern";}
    const double getX() const { return m_x; }
};
class Scanner
{
private:
    Power m_power;
public:
    Scanner() {std::cout<<"Scannern";}
    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<<"Printern";}
    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<<"Copiern";}
    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可以用3.142.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);
}

我不知道怎么做这个。简而言之,ScannerPrinter和其他存在的类都是专用的类,它们只执行一项任务,其计算方式是唯一的,并且它们都使用Power中的一些通用变量(除了它们自己的变量之外)。我不认为将公共变量移动到每个类是非常有效的,因为它们只会使代码膨胀,而且,正如我所理解的那样,"如果您可以使用存储类而不是一遍又一遍地重复相同的变量,就使用它"(不是我的话,这是真的吗?)然后,我希望能够实例化这些类,但一次只有一个活动,以节省内存。

例如,假设一个类生成一个包含1mil个值的数组,然后另一个类生成1mil个不同的值,以此类推。想象一下,该数组在内存中的次数与实例化类的次数一样多。我不想那样。Copier的目的是一次只调用一个类(基于条件)。完成工作吗?打电话给另一个,但是忘记之前做过的任何事情,重新开始。所有这些都可以通过一个小部件调用,例如select from list, click&go,这将在稍后添加。

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


好吧,经过一些尝试,我不能做我想要的,所以我想回到我最初的想法,即使这意味着继承。所以我写了这段代码,在这里我改变了名字,使它更有意义(?):

#include <iostream>
class Garage
{
protected:
    double m_x; // gas, tires, etc, that all cars use, reside in the Garage
public:
    Garage() {std::cout<<"Garagen";}
    virtual ~Garage() {std::cout<<"~Garagen";}
};
class Audi: virtual public Garage
{
public:
    Audi() {std::cout<<"Audin";}
    void f(const double &x) { m_x=x; std::cout<<"Audi::f("<<x<<")n";}
};
class Bmw: virtual public Garage
{
public:
    Bmw() {std::cout<<"Bmwn";}
    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<<"Drivern";}
    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,在这里,也负责进一步使用m_x,因为它的m_y(这就是为什么代码有点不同)。


我想指出的是,我并不固定保持这段代码,或任何其他,我愿意改变和适应,只要我达到我的目的。但由于我是初学者,我不能做太多的组合,所以我只能把我得到的结果呈现出来,试图让别人理解我。上面的程序,就像它一样,在运行时,给出了我想要的,甚至有可能产生一个循环,这将使我在GUI中更容易使用它,稍后。这些名称,就其本身而言,在组合中最有意义,Garage 有-a Bmw,这就是我所尝试的,但我无法获得我想要的。因此,即使这使用了继承,并且Audi 是-a Garage没有意义,我保留了这些名称,以表明我对组合的初步尝试。我发布这篇文章的主要原因是为了展示我想要这个程序做什么。在main()中发生的事情将在GUI中使用,我正在考虑Qt,因为我希望它在所有3个主要操作系统上运行。因此,有可能一次调用一辆车,使用它,也能够存储以前的信息,而不会在内存中有过时的对象,只有m_x *nr_of_cars,将使它更容易使用。

这是一种方法。

{ // 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

使用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));
}

也许你真正想要的是一个带标签的联合。遵循"五"原则。