简体   繁体   中英

C++, adding temporary objects to a list, without dynamic memory allocation

I'm writing code for an embedded platform, therefore I cannot use the normal new operator.

Now I want to add arbitrary objects to a list, just like this.

tp.add(DerivedA("David")); 
tp.add(DerivedB("Max"));
tp.add(DerivedC("Thomas"));

For the reason of code duplication I don't want to write something like this:

DerivedA david("David");
tp.add(david); 
...

A solution, but not very pretty style would be this:

tp.add(new (myalloc(sizeof(DerivedB))) DerivedB("John")); 
// using placement-new works

Now I tried to add a temporary object, passed by pointer:

tp.add(&DerivedA("David")); 

Theoretically this could work, but the compiler complains (with good reason) about passing a pointer to a temporary object (-fpermissive).

Is there a clean way of doing what I want to?

Here is a full example:

#include <iostream>

using namespace std;

class Base // base class
{
public:
    Base();
    int size;
    char name[100];
};

class Derived:public Base
{
public:
    Derived(char* name);
};

class ThirdParty
{
public:
    void add(Base* obj);
    void addTemp(Base* tempObj);
    Base* list[10];
    int index;
};


void* myalloc(int size){
    void* p;
    // ...
    // allocate memory in a static memory pool
    // ...
    return p;
}

void memcpy(void* to, void* from, int size){

}


int main()
{
    ThirdParty tp;

    // The ugly style:
    tp.add(new (myalloc(sizeof(Derived))) Derived("John")); // using placement-new works

    // The beauty style (compiler complains here):
    tp.addTemp(&Derived("David")); // create temporary object here, which is copied and added to the list
    tp.addTemp(&Derived("Max"));
    tp.addTemp(&Derived("Thomas"));

    return 0;
}


Base::Base()
{
    size = sizeof(Base);
}

Derived::Derived(char *name)
{
    size = sizeof(Derived); // make size of this object available for a base-pointer
}

void ThirdParty::add(Base *obj)
{
    list[index++] = obj;
}

void ThirdParty::addTemp(Base* tempObj)
{
    Base* newObj = (Base*) myalloc(tempObj->size); // let third party allocate memory
    memcpy(newObj, tempObj, tempObj->size); // copy the temporary object
    list[index++] = newObj;
}

If you use C++11, you could write a forwarding function to do the work for you:

template <typename T, typename... Args>
T* make (Args&&... args) {
    return new (myalloc(sizeof(T))) T { std::forward<Args>(args)... };   
}

You'd then add an object to your list like so:

tp.add(make<Derived>("John"));

My preferred solution now is the following macro:

#define m(x) new (myalloc(sizeof(x))) x

now I can add a new object with this code:

tp.add(m(Derived("Isabella")));

Can you not just override new to use myalloc ? If you do notcwant to do this globally, you certainly can do it for Base

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM