2

I try to replicate C++ destructors and constructors in my c programming. That means for every object or struct there is an initialization function and a destruct function which frees all of the objects resources like so:

struct MyObject {
      struct string a;
      struct string b;
      struct string c;
};

ConstructMyObject(struct MyObject *obj) {
     ConstructString(&obj->a);
     ConstructString(&obj->b);
     ConstructString(&obj->c);
}

DestructMyObject(struct MyObject *obj) {
     DestructString(&obj->a);
     DestructString(&obj->b);
     DestructString(&obj->c);
}

The destruct function is called at the end of every function scope just like in c++ only that i put it manually there. So now in DestructMyObject function I call the destructors of every struct string type because for the struct string object i would also have a destruct function written just like for the struct MyObject Object.

Example with my problem:

int main {
     struct MyObject Object1;
     ConstructMyObject(&Object1);
     ...
     ...
     ...
     TransferOwnershipFunction(Object1.b); /*takes a struct string object as argument*/
     ...
     ...
     ...

     DestructMyObject(&Object1);

    return 0;
}

You see that i have transfered ownership of one Member of Object1 to another function but everything of Object1 will be destroyed by its destructor in the main function.

How do c++ destructors handle this kind of situation? I don't want that the destructor for struct string b is called at the end of main but it will be called because i call the destructor for MyObject. The function TransferOwnershipFunction(...) is now responsible for freeing the string object.

EDIT Somebody knows how a rust compiler would resolve this issue? So in Rust would i need to clone the struct string object I'm passing to TransferOwnershipFunction or is there another way of doing it because cloning (or copying i guees) seems to be a very expensive operation.

The Guest
  • 59
  • 6
  • 8
    In C++ there is a move constructor and copy constructor. Independent of what you do, if you move an object, the original object is aware that it is moved and transfers ownership of the data. The original objects destructor is called anyway, there is just nothing to free there. You shuold do something like `string_move(struct string *to, struct string *from) { to->data = from->data; from->data = NULL; }` – KamilCuk Oct 18 '19 at 14:38
  • 1
    Your example is hard to follow, but this seems to be no different than when a C++ programmer refuses to obey the [rule of 3](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). Thus C++ does *not* handle this -- the programmer handles it. – PaulMcKenzie Oct 18 '19 at 14:46
  • please provide a code of struct string – Sergey Aleksandrovich Oct 18 '19 at 15:49
  • struct string would hold a pointer to some heap memory and in its destructor i would free that pointer. – The Guest Oct 19 '19 at 10:33

1 Answers1

1

From my point of view main() should be responsible for creating and deleting of Object1. And TransferOwnershipFunction() should work with a copy of Object1.b. In this case:

  1. You need to create functions which work as analog of copy constructor and assignment operator (for C++03). Also move constructor and move assignment operator were added in C++11.
  2. In C++03 copy constructor and assignment operator are generated implicitly if you don't declare them. By default they copy objects by member of class (not by bytes in memory) using copy constructor of each member (except simple types like int, double...). So you need to imitate of passing Object1.b by value with calling of copy constructor: in TransferOwnershipFunction create new object of type struct string, copy content of it by member. If struct string contains a raw pointer as member and you call malloc for this member in struct string's constructor and free in destructor than in copy constructor of struct string you need to call malloc than copy all content from passed variable. Don't forget to call destructor at the end of TransferOwnershipFunction.
  3. According to RAII you need to call destructors in reverse order relation to order of creating objects (order of constructors).