I am porting C# app into C linux app. I am confused with construction and destruction in "modern" (C 11 ?). I always thought you have to use new/delete
but now it appears C recommendation is not to do so (is this correct or I read a wrong blog?).
What I have roughly (there are 6 subclasses of B
and BRec
atm):
class ARec : public BRec
class A : public B
. . .
class Factory
BRec GetRecord(WrapperStruct s)
{
if(s.Type == 'A')
{
A* a = (A*)s.Data;
auto rec = ARec((ushort)a->Num);
rec.OtherField = a.OtherField;
return rec;
}
. . .
main
// separate pthread
void* Logger(void* arg) {
int* thread_state = (int*)arg;
auto f = Factory();
WrapperStruct item;
while (true)
{
q->try_dequeue(item);
auto rec = f.GetRecord(item);
auto bytes = f.GetBytes(rec);
// write bytes to file ...
delete bytes;
if(*thread_state == -1)
pthread_exit(0);
}
Question - how does compiler would know when to delete s.Data
in factory method? Same - rec
if it was created in a class method and then crossed to other method (while
in Logger)? Is there a simple guide how to manage variables' memory in C 11 ?
EDIT: s.Data
contains ref to an object created in a 3rd party dll and can be of different types hence the s.Type
field
CodePudding user response:
Smart pointers are the key.
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
std::unique_ptr<Foo> bar = std::make_unique<Foo>();
Shared pointers can be copied. They do reference counting. When the reference count drops to zero, they'll delete their contents automatically.
Unique pointers can't be copied. They can be copied by reference. When the unique pointer goes out of reference, it frees the object for you.
So it works a lot like Java now.
void notAMemoryLeak() {
std::shared_ptr<Foo> foo = std::make_shared<Foo>();
}
Other than that, you treat them like pointers. The syntax for their use at this point is identical, except you're passing smart pointers, not Foo *.
void myFunct(std::unique_ptr<Foo> &foo) {
cout << "Foo: " << foo->getName() << "\n";
}
The make_shared
and make_unique
can take the same arguments as any of your Foo's constructors, so feel free to pass stuff.
I do one more thing:
class Foo {
public:
typedef std::shared_ptr<Foo> Pointer;
...
};
Foo::Pointer foo = std::make_shared<Foo>();
Sometimes I also create static methods to make it even cleaner. This is stylistic and not necessary. Some people might fault me. But it's clean and easy to read.