Sign in to follow this  
lXciD

Pointer vs non pointer as member variable

Recommended Posts

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. :)

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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++.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this