Pointer vs non pointer as member variable

Started by
8 comments, last by dmatter 14 years, 7 months ago
Hi I would like to ask what's the difference between pointer and non pointer as member variable. If we a class A.

class A
{
public:
    A();
    ~A();
};
Pointer as member variable.

class B
{
public:
    B();
    ~B();
private:
    A * m_A;
};
Non pointer as member variable.

class C
{
public:
    C();
    ~C();
private:
    A m_A;
};
Some of my assumptions: * In Class B, Class A lifetime is not bound to Class B. * In Class C, Class A lifetime is bounded to Class C. Thus if Class C is deleted, Class C will be deleted. * When Class C is deleted, both Class C and Class A destructor will be called. If my 2nd assumption is true, what's the order the constructor will be called? Maybe I can do a small test. BRB. :)
Advertisement
Sorry if I ask you, but is this homework?

Anyway, your assumptions are correct. For the order do a small test (it is not allowed to ask for homework here). A tip: you should be able to use data members inside the constructor.

If !homework, why do you need to know that? For example, there are also other reasons to choose one option over the other...
Its funny how I post the question and went to find out the answer myself. Apparently I had some great finding at least to me.

Here's my code.

#include "stdafx.h"#include <iostream>class A{public:    A()    {        std::cout << "A constructor is called" << std::endl;    }    ~A()    {        std::cout << "A destructor is called" << std::endl;    }};class B{public:    B( int i )    {        std::cout << "B constructor is called with i = " << i << std::endl;    }    ~B()    {        std::cout << "B destructor is called" << std::endl;    }};class C{public:    C()        : m_B( 0 )        , m_A()    {        std::cout << "C constructor is called" << std::endl;    }    ~C()    {        std::cout << "C destructor is called" << std::endl;    }private:    A m_A;    B m_B;};int _tmain(int argc, _TCHAR* argv[]){    C * c = new C();    delete c;    int i;    std::cin >> i;	return 0;}


Here's the result

A constructor is called
B constructor is called with i = 0
C constructor is called
C destructor is called
B destructor is called
A destructor is called

Apparently, my assumption is correct. :)

The interesting things is that the order of the constructors and destructors being called. The initialization part of the C constructor doesn't affect the order. It is the order you declare your variables in the class that dictate the order of the constructor being called.

This was tested on Visual Studio .NET 2005 so behavior may varies. :)

I think I learnt something today. Sorry for this self answered post. :X
Both of your assumptions are correct.

Destructors are destroyed in the opposite order the constructors are called. You may as well read this for information about destructors that you may wish to know. Then, read much of the rest of the website! It has a lot of good information.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Its not a homework. Its just that I always wonder why many stored std::string as a non pointer member variable but other defined class as pointer member variables. What's the reason to use one over the other.

I thought that there should be a good reason to use either one. I was thinking lifetime of an object is a good place to find that reason.

Its more for improving my ways of programming. Try to make my code more meaningful and with more intend? rather than blinding follow without knowing. :X
Thanks guys for your prompt reply and info. :D Thanks for the link nobodynews! I was googling a while before I posted here and couldn't find anything worth while reading. maybe I was searching it wrongly. :P
It's good to test things out yourself but that doesn't always mean the behavior will be the same across all compilers. In this case your observations happen to be conform to the standard.

Quote:I thought that there should be a good reason to use either one. I was thinking lifetime of an object is a good place to find that reason.
That is one reason. The other is polymorphism. Yet another reason is you might want multiple objects to refer to some other, common object. Such as sharing a large resource like an image, 3D model, sound, etc. But believe it or not, you still don't need to use pointers. At least not directly. Smart Pointers (through the tr1:: namespace in certain compilers such as Visual C++ 2008 or the boost:: namespace if you downloaded the boost library) can allow you to reap the benefits of pointers without the messiness of having to clean up after them.

edit: linkied the tr1 and boost namespaces to documentation on them

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Quote:Original post by lXciD
I always wonder why many stored std::string as a non pointer member variable but other defined class as pointer member variables. What's the reason to use one over the other.

The only reason to use a pointer as a member variable is when you implement a resource managing class such as string, vector or shared_ptr, and since these classes already exist, you should rarely have pointer members in your own classes.

If you don't agree, you probably never heard of exception safety.
Also note that if you have nontrivial destructor, for example you allocate memory for you pointer member in constructor and deallocate in destructor, you'll most likely have to write copy constructor and assignment operator as well for your class (rule of three), and these may come to play even if you don't explicitly call them (the compiler may create temporaries).
1) Constructors are always called in the order the members are defined - it's often considered good practice to try keep the initialiser list in the same order to help avoid possible mistakes. If you can avoid writing code that actually relies on this behaviour in the first place then that's probably a good thing to do, IMO.

2) Destruction of members happens in the opposite order to construction.

3) Pointers are useful when it's inappropriate/impossible to #include a header that defines the member, when you want to stagger lifetimes, when you want to share instances, when you need polymorphism and when you want to fully hide an implementation (see the PImpl Idiom). In C they're also used to implement pass by reference semantics, C++ has actual references for this though.

4) Raw pointers (defined using an asterix: *) are seldom used in modern C++ for anything other than low-level resource management and interfacing with old libraries. They make it harder to ensure exception safety and make it easy to leak memory.

5) RAII containers, including smart pointers (shared_ptr, weak_ptr, scoped_ptr, intrusive_ptr, auto_ptr, shared_array, scoped_array, optional) and collections (vector, ptr_vector, list, ptr_list, etc), along with references are for solving the other 99.9% of scenarios where we might have had to use raw pointers in classical C++.

This topic is closed to new replies.

Advertisement