New to pointers

Started by
6 comments, last by Aardvajk 11 years, 8 months ago
Hey guys!

I'm not new to programming, but it's been many years since I really used C++, and I don't think we even touched on pointers(it was in highschool). Anyways, I have some working code, but since I'm not a pointer expert I wanted to make sure that I was doing this correctly.

Currently, I'm working on a small prototype for a game to kind of help me get some basic ideas down as well as help me get back into the way C++ does things. I'm using SFML and my question really applies to how I have my game screens set up. In each game screen, it holds a pointer to the RenderWindow so that when Draw is called the RenderWindow would not have to be passed before each frame is drawn.

Since the RenderWindow will have its own destructor called all I do is set the pointer to 0. Is that all I really have to do?

Here's some code just to be certain.

This is not all my code, just the code in question. Like I said, I wanted to make sure that I'm doing this correctly. Everything compiles and it runs fine!

tl;dr

Is this an acceptable use of pointers?


class BasicGameScreen
{
private:
//Window used for Rendering
sf::RenderWindow *MainApp;
public:

void Initialize(sf::RenderWindow &App)
{
MainApp = &App;
}

void :Draw()
{

//drawing whatever
MainApp->Draw(Background);
MainApp->Draw(Sprite);
}

~BasicGameScreen()
{
MainApp = 0;
}
}
Advertisement
No problems with that really. You might like to consider passing the MainApp pointer into BasicGameScreen's constructor so you avoid having a BasicGameScreen ever exist without the pointer initialised - as is if you called Draw() before Initialize() by mistake, you'd crash in a nasty way.

The other approach to consider is to pass a reference to MainApp to the Draw() method as a paramter. I generally prefer this when possible as it reduces the amount of bookeeping within classes and makes it easier to re-use a class in the future.

The other option would be to store a reference to MainApp rather than a pointer, initialised again in the constructor but having reference members of classes is a tricky business and can have implications for storing instances of your class in standard containers etc.

No problems with that really. You might like to consider passing the MainApp pointer into BasicGameScreen's constructor so you avoid having a BasicGameScreen ever exist without the pointer initialised - as is if you called Draw() before Initialize() by mistake, you'd crash in a nasty way.

The other approach to consider is to pass a reference to MainApp to the Draw() method as a paramter. I generally prefer this when possible as it reduces the amount of bookeeping within classes and makes it easier to re-use a class in the future.

The other option would be to store a reference to MainApp rather than a pointer, initialised again in the constructor but having reference members of classes is a tricky business and can have implications for storing instances of your class in standard containers etc.

If in your case MainApp pointer can never be null in a BasicGameScreen instance you need to use a reference as that makes that clear in the semantics of the class. A reference has to be initililased at the time to class instance is created, which means that whatever it aliases needs to exist as long as this class exists.

If you can't guarantee either of these conditions use a pointer. If you can't guarantee condition two and you are using a reference you can get a reference that's pointing at random memory which the runtime will always try to interpret as the definition of the class being referenced.

Having pointer or reference parameters can mean problems with any type of copy construction, that's the problems you face with STL containers anyway. If a shallow copy is fine, this is the copy constructor C++ will generate for you, there should be no trouble. However when a shallow copy isn't fine you will have to define your own assignment and copy constructors to do a deep copy

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion


Having pointer or reference parameters can mean problems with any type of copy construction, that's the problems you face with STL containers anyway. If a shallow copy is fine, this is the copy constructor C++ will generate for you, there should be no trouble. However when a shallow copy isn't fine you will have to define your own assignment and copy constructors to do a deep copy


How do you suggest defining a default constructor or an assignment operator for a class containing a reference?

The simple rule of "if it cannot be null, use a pointer" applies to function parameters but cannot be universally applied to class members as well.

[source]
class xxx
{
public:
xxx(int &a) : a(a) { }
xxx(const xxx &b) : a(b.a) { }

int &a;
};

void f()
{
int z;

std::vector<xxx> a;
a.push_back(xxx(z));
}
[/source]

Won't compile (with GCC anyway). A class containing a pointer member can easily be made to work however.
Isn't it just a warning you are getting about z not being inialised as MSVC2010 compiles that code fine.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

Hmm, checked again, definatly an error from GCC but it is complaining that the default assignment operator is not sufficient, which admittedly seems a bit odd.

Not sure if GCC or VS is correct here as far as standard is concerned. I thought a class containing a reference member was non-copyable but thinking about it now, I'm not sure why.
With C++03, in order for a type to be usable in a standard library container, it needs to have both a copy constructor and an assignment operator. With C++11, the situation is a little more complex. Only some of the operations require an assignment operator to be available. Some functions only need the type to be move constructable, copy constructable, etc. Since MSVC 2010 is more or less a C++11 compiler, it doesn't freak out if there's a missing assignment operator where other compilers might complain. If you change your function to:

void f() {
int z;

std::vector<xxx> a;
a.push_back(xxx(z));

std::vector<xxx> b;
b = a;
}

it should start complaining about the container assignment since container assignment requires that assignment of the contained type be allowed.

With C++03, in order for a type to be usable in a standard library container, it needs to have both a copy constructor and an assignment operator. With C++11, the situation is a little more complex. Only some of the operations require an assignment operator to be available. Some functions only need the type to be move constructable, copy constructable, etc. Since MSVC 2010 is more or less a C++11 compiler, it doesn't freak out if there's a missing assignment operator where other compilers might complain.


Interesting, thanks SiCrane.

This topic is closed to new replies.

Advertisement