Sign in to follow this  
Tano_ITA

A little question on pointers

Recommended Posts

Quote:
Original post by Tano_ITA
Hi,
if i create a new object like this:


for(i = 0; i< 10; ++i)
{
ServerSystem *server = new ServerSystem();
}


why this isn't an error?


What kind of error were you expecting?

you will get a memory leak at run time, but it is a perfectly valid piece of code.

Share this post


Link to post
Share on other sites
Ok, thanks for the replyes. but if i want to access a particolary server object? For example, i want to delete 2 of 10 objects. Can i do that?

Thanks a lot. I know that's a stupid question, but i'm curious.. And sorry for my bad english! :)

Share this post


Link to post
Share on other sites
Quote:
Original post by neomech
you will get a memory leak at run time, but it is a perfectly valid piece of code.
Not necessarily. The object's constructor may well be doing some voodoo magic to destroy itself when some event happens (such as the application shutting down).

Share this post


Link to post
Share on other sites
Quote:
Original post by Tano_ITA
Hi,
if i create a new object like this:


for(i = 0; i< 10; ++i)
{
ServerSystem *server = new ServerSystem();
}


why this isn't an error?


This is stuff for what a compiler would yield a warning message. Warning (as opposed to error), because (as many people already pointed out) it is valid code, but still you are (probably) doing something wrong here. But as far as I know, no current compiler would print a warning for that (but e.g. gcc prints warning for every call to gets(), which is a valid function, but dangerous).


edit:typo

Share this post


Link to post
Share on other sites
Quote:
Original post by Tano_ITA
Ok, thanks for the replyes. but if i want to access a particolary server object? For example, i want to delete 2 of 10 objects. Can i do that?

Thanks a lot. I know that's a stupid question, but i'm curious.. And sorry for my bad english! :)


And for this question?

Share this post


Link to post
Share on other sites
Quote:
Original post by monkey8751
It is an error in that you aren't going to be able to delete any of those pointers you created.


C++ is built on premise that "user knows better". In this case, user wants to allocate several objects.

Valid, and sane, yet somewhat advanced example (see boost's asio TCP connection examples):
class ServerSystem {
ServerSystem() {
registerEvent(this, onReceive, &ServerSystem::onReceive);
registerEvent(this, onShutdown, &ServerSystem::onShutdown);
}
void onShutdown() {
delete this;
}
};


onShutdown gets called by some external handler.

While purists will start killing kittens when seeing such code, there is nothing wrong with it, and sometimes makes perfect sense.

This is also idiomatic approach for memory managed languages. There, references are tracked implicitly. So even if user loses a reference to an object, memory manager still has it. But the by far most important point: someone, somewhere, somehow needs to track what a certain byte of memory represents. It could even be DRAM itself. Or memory manager. Or meta-bits in memory. Or someone. In above example, event manager (in asio's example it's the IOCP) keeps track of this reference.

General advice for C++ is to de-allocate in same context as you allocate. But this is not even remotely required, and sometimes not even desired. Code such as this:
void concatStrings(string * s1, string * s2) {
return new string(s1, s2);
}
is undesirable due to design/implementation coupling. Since C++ makes no distinction of how pointee was allocated, such function will implicitly need to use consistent allocation scheme.


All that said, general advice still holds. Manage what you allocate. Almost without exception, it makes code cleaner and simpler to follow. But if using C++, look into other options. After all, manual memory management is the defining trait of C++.

Quote:
And for this question?


You somehow need to find them. Unless you remember where you put something, you will never find it again.

And don't do that. Just because of above options, this isn't a legit example of such practices. Allocate, remember, de-allocate. It will be a long time before you find a legit example where it may be desirable to forget what you allocated.

Share this post


Link to post
Share on other sites
You probably want an array (or std::vector, or some usage of smart pointers) of pointers.
ServerSystem *server[10];
for(int i = 0; i < 10; ++i)
{
// chance for memory leak if an exception occurs here
server[i] = new ServerSystem();
}

delete server[2];
server[2] = NULL;
int x = rand() % 10;
if(server[i])
{
server[i]->do_something();
}
// chance for memory leak if an exception occurs here
server[2] = new ServerSystem();
for(int i = 0; i < 10; ++i)
{
delete server[i];
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Tano_ITA
Quote:
Original post by Tano_ITA
Ok, thanks for the replyes. but if i want to access a particolary server object? For example, i want to delete 2 of 10 objects. Can i do that?

Thanks a lot. I know that's a stupid question, but i'm curious.. And sorry for my bad english! :)


And for this question?


We must have missed that, 3 posts in a minute :D

As for your question: One way would be an std::vector<> or std::list<>. You could then remove your objects as wanted. If they have to be pointers for whatever reason, you would either have to manually delete the particular vector-item and then remove it, or use e.g. boost::shared_ptr<>:


class Foo {};

// Probably best way:
int main () {
::std::vector <Foo> foos;
foos.push_back (Foo ());
foos.push_back (Foo ());
foos.pop_back();
// remaining instances will be cleaned up properly
}

// Worst way:
int main () {
::std::vector <Foo*> foos;
foos.push_back (new Foo ());
foos.push_back (new Foo ());
delete foos.back();
foos.pop_back();
// remaining instances will not be cleaned up properly
}

// Okay way, if pointers are mandatory:
int main () {
::std::vector < ::boost::shared_ptr <Foo> > foos;
foos.push_back (::boost::shared_ptr <Foo> (new Foo ()));
foos.push_back (::boost::shared_ptr <Foo> (new Foo ()));
foos.pop_back();
// remaining instances will be cleaned up properly thanks to shared_ptr
}



The magic is that std::vector or std::list or other containers from the STL are based on the "Resource Acquisition Is Inititialization" (RAII) idiom.

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