By Gordon Williams


2019-09-11 09:14:29 8 Comments

I've got an issue where I'm having to use a C++ library in an embedded system. The library (Tensorflow Lite for microcontrollers) is designed for embedded systems and for use without malloc/free, however the examples of using it define everything on the stack and there is no default constructor available.

Defining on the stack doesn't work in my application because I need to be able to initialise it in a function which will then exit. What I need is to be able to allocate a memory area (with my own allocator) that contains everything I need and then initialise everything in that memory area.

I've tried to boil this down to a bare minimum example:

// This is a third party library
class OtherClass {};
class MyClass {
 private:
   OtherClass &c;
 public:
    MyClass(OtherClass &c) : c(c) {};
};

// My code
typedef struct {
  OtherClass otherClass;
  MyClass myClass;
} MyAllocatedData;

char dataIsSomewhere[sizeof(MyAllocatedData)];
MyAllocatedData *pData = (MyAllocatedData *)dataIsSomewhere;

int main() {
  // dataIsSomewhere gets allocated somewhere on demand
  // now we want to initialise everything
  pData->myClass = MyClass(pData->otherClass);  
  return 0;
}

The compilation of this fails with:

test.cpp: In function ‘int main()’:
test.cpp:20:45: error: use of deleted function ‘MyClass& MyClass::operator=(MyClass&&)’
   pData->myClass = MyClass(pData->otherClass);
                                             ^
test.cpp:3:7: note: ‘MyClass& MyClass::operator=(MyClass&&)’ is implicitly deleted because the default definition would be ill-formed:
 class MyClass {
       ^~~~~~~
test.cpp:3:7: error: non-static reference member ‘OtherClass& MyClass::c’, can’t use default assignment operator

Is there a nice way around this? Patching the library would be a possibility but I'd rather not.

Maybe I could define my own new operator for MyClass which allocated it in the correct place? It doesn't seem ideal though.

2 comments

@Jarod42 2019-09-11 09:38:40

Use proper contructor:

struct MyAllocatedData
{
  MyAllocatedData() : otherClass(), myClass(otherClass) {}

  OtherClass otherClass;
  MyClass myClass;
};

And then

int main() {
  MyAllocatedData data;
  // ...
}

or if you need to place it in memory, use placement new:

MyAllocatedData* pData = new (dataIsSomewhere) MyAllocatedData{};

@Gordon Williams 2019-09-11 09:55:30

Thanks! This would be great for the example, however the example I posted was deliberately simplified. The actual issue I have (involving tflite::MicroInterpreter) requires more arguments that couldn't be supplied inside MyAllocatedData - so while i could create a class to handle it, things get complicated quite quickly as I need to allocate a variable size block of data on the end of the struct as well. placement new seems like the trick I need.

@Gordon Williams 2019-09-11 10:09:30

Accepting your answer because I believe you were first to post the suggestion as a comment.

@molbdnilo 2019-09-11 09:20:28

You can use placement new to create an object in a given location:

new (&pData->myClass) MyClass(pData->otherClass);  

@Max Langhof 2019-09-11 09:38:34

And of course, you then have to delete what you newed.

@Sander De Dycker 2019-09-11 09:45:26

the same should probably be done for the OtherClass instance as well, otherwise it remains uninitialized

@Gordon Williams 2019-09-11 09:50:38

This looks spot on for what I need, thanks! However, I do get static void MyClass::operator delete(void*)’ is private within this context errors (because in tflite the 'delete' operator is defined as a private empty method). Any idea how I could work around that? For now I modified tflite's source to make delete public and it's fine, but obviously it'd be better if I could get away without patching source - and I don't really understand why delete is even called

@molbdnilo 2019-09-11 10:04:29

@MaxLanghof Absolutely not in this case. Placement new only creates a new object; the destructor will take care of its destruction.

@molbdnilo 2019-09-11 10:07:30

@GordonWilliams You shouldn’t use delete.

@Sander De Dycker 2019-09-11 10:08:49

@MaxLanghof : you shouldn't delete, but you do need to call the destructor manually : pData->myClass.~MyClass();

@Gordon Williams 2019-09-11 10:10:33

My issue is that I'm not using delete at all, but the compiler is still complaining that it isn't public (it won't happen in the example, but it does with tflite because the delete op is private)

@Max Langhof 2019-09-11 12:11:03

I stand corrected! Sorry for the incorrect information @GordonWilliams!

Related Questions

Sponsored Content

45 Answered Questions

[SOLVED] What does "Could not find or load main class" mean?

  • 2013-08-07 03:02:46
  • Stephen C
  • 2426363 View
  • 1229 Score
  • 45 Answer
  • Tags:   java class main

50 Answered Questions

17 Answered Questions

[SOLVED] Are static class variables possible in Python?

30 Answered Questions

[SOLVED] What are the differences between struct and class in C++?

28 Answered Questions

[SOLVED] When to use struct?

  • 2009-02-06 17:37:55
  • Alex Baranosky
  • 254078 View
  • 1333 Score
  • 28 Answer
  • Tags:   c# struct

24 Answered Questions

[SOLVED] When should you use a class vs a struct in C++?

  • 2008-09-10 16:29:54
  • Alan Hinchcliffe
  • 372643 View
  • 870 Score
  • 24 Answer
  • Tags:   c++ oop class struct ooad

16 Answered Questions

[SOLVED] Why Choose Struct Over Class?

18 Answered Questions

[SOLVED] What's the difference between struct and class in .NET?

16 Answered Questions

[SOLVED] Struct Constructor in C++?

8 Answered Questions

[SOLVED] Difference between 'struct' and 'typedef struct' in C++?

  • 2009-03-04 20:41:12
  • criddell
  • 483040 View
  • 790 Score
  • 8 Answer
  • Tags:   c++ struct typedef

Sponsored Content