Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : about memory management

I'm a bit new to C++ and been doing programming in Obj-C and Java up until now.

Say, I have a class:

class Person {

private:
   Wife *current_wife;
   //.....
};

So obv I need to implement a setter method to change the Wife instance variable.

Like this:

Person::SetCurrentWife (Wife *new_wife) {

    current_wife = new_wife;
}

That would be a shalllow copy.

So somewhere from the main loop or something I call:

Person *some_person = new Person();
...
Wife *wife = new Wife ();
some_person->SetCurrentWife(wife);

So I'm confused: will there be a memory leak here? Should I delete the wife object here or in Person's destructor? In Obj-C I would release the current wife and then send a retain message to wife object above, but what is the proper way of doing setter methods in C++?

like image 342
Random Avatar asked Dec 20 '11 13:12

Random


People also ask

What is memory management in C language?

Dynamic memory management in C programming language is performed using the malloc() , calloc() , realloc() , and free() functions. These four functions are defined in the <stdlib.h> C standard library header file. It uses the heap space of the system memory.

Why is memory management important in C?

Memory management requires that the programmer provides ways to dynamically allocate portions of memory to programs, when requested, and free it for reuse when it is no longer needed. In any advanced computer system, where more than a single process might be running at any given point in time, this is critical.

What is memory management and its types?

Memory management is the functionality of an operating system which handles or manages primary memory and moves processes back and forth between main memory and disk during execution. Memory management keeps track of each and every memory location, regardless of either it is allocated to some process or it is free.

What is the main function of memory management?

Memory Management is the process of controlling and coordinating computer memory, assigning portions known as blocks to various running programs to optimize the overall performance of the system. It is the most important function of an operating system that manages primary memory.


3 Answers

It depends on what you're trying to do. First, as Kerrek SB has commented, you don't want to use pointers if value semantics can be applied: if Wife is copyable and assignable, there's almost no reason to allocate it dynamically. In this case, however, I'm guessing that Wife derives from Person (although perhaps a decorator for Person would be more appropriate, since the fact that a given Person isA Wife can change over time), that there might even be types derived from Wife (and that Person::current_wife might want to hold one of these), and that in fact, Wife has identity; you don't want copies of the same wife all over the place.

If this is the case, then you really have to define a protocol for the interactions of other classes with Wife. Typically, the lifetime of Wife will not depend on the Person who holds it (although if it is a decorator, it might), so Person should just hold a pointer to it, as you've done. Most likely, the Wife object will have various functions which—implicitly or explicitly—control its lifetime: you might have something like:

void Wife::die()
{
    //  ...
    delete this;
}

for example. In that case, however, whoever is married to Wife will have to be informed, so that current_wife doesn't point to a dead spouse. Typically some variant of the observer pattern can be used for this. (Note that you have exactly the same issue in Java; you don't want Person::current_wife to point to a dead Wife. So you'd still need a Wife::die() function, and the observer pattern to notify the spouse.)

In cases like this (which in my experience represent the vast majority of dynamically allocated objects in C++), about the only difference between C++ and Java is that C++ has a special syntax for calling the “destructor”; in Java, you use the usual function call syntax, and you can give the function any name you wish (although dispose seems widely used). The special syntax allows the compiler to generate additional code to release the memory, but all of the other activities associated with the end of the object lifetime still have to be programmed (in the destructor, in C++—although in this case, it might make sense to put some of them directly in the Wife::die function).

like image 182
James Kanze Avatar answered Sep 29 '22 23:09

James Kanze


You should use a smart pointer.

If you use regular pointer, practice caution!

You should delete the old current_wife member both on the destructor and on the set method. Setting a new wife will lead to the memory leak of the old one, as the pointer to that allocated memory is lost (unless you manage the memory outside the class - see below).

But even doing so, you need to make sure that no-one outside the class can delete the member. You have to decide whether memory management is left to the class or dispached to the outside of the class, and stick to it.

like image 29
Luchian Grigore Avatar answered Sep 30 '22 00:09

Luchian Grigore


Smart pointers can help you

using boost::shared_ptr; // or std::shared_ptr, or std::tr1::shared_ptr or something like this
class Person { 

private: 
   shared_ptr<Wife> current_wife; 
   //..... 
}; 

Person::SetCurrentWife (shared_ptr<Wife> new_wife) { 

    current_wife = new_wife; 
} 

And now you should not delete any wife at all.

shared_ptr<Person> some_person ( new Person );
...  
shared_ptr<Wife> wife ( new Wife );  
some_person->SetCurrentWife(wife);  
like image 25
Alexey Malistov Avatar answered Sep 30 '22 01:09

Alexey Malistov