Sign in to follow this  

C++: Best way to initialize classes

This topic is 3631 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

C++ has so many ways to do things that I haven't yet learned when it's best to do such things. What is the best way to create a new instance of a class? I know there are many ways, and it depends on the situation, so what is the best way for each method? I've seen a lot of code all use different ways. I don't believe it can just be a preference issue, because each one works in different ways. I can think of the following ways (note that each X.5 just adds a pointer thingy to the first myClass): 1:
myClass theObject = new myClass(constructor_params);
1.5:
myClass* theObject = new myClass(constructor_params);
2:
myClass theObject(constructor_params);
2.5:
myClass* theObject(constructor_params);
3:
myClass theObject = myClass(constructor_params);
3.5:
myClass* theObject = myClass(constructor_params);
4+? Any other ways to do it? This is what my understanding is: Note that X.5 all ask the same question: make a pointer to the thing or not? My understanding is that making big classes as pointers is faster? Because when you pass them as arguments you can just pass the pointer. Also, what counts as a "big" class?) Or is it better to not use pointers and pass by reference? Am I misunderstanding some big concepts? Also, arrows are cool (->). Re: 1: I know that with the new keyword, I also have to remember to use delete. (I don't have to (with a few exceptions, I assume) explicitly call destructors (with or without new), do I?) I see new used a lot with pointers. Is there something to that? I know that new dynamically allocates memory. Does that mean that I should use it for classes that have the potential to use more memory? Should that property be obvious to me when I see it? Re: 2: How do I know when I can do this without problems? Re: 3: 3 and 2 are similar; I read somewhere that 3 was a safer way to do it, as sometimes 2 could be initialized incorrectly if the constructor parameter was another class' constructor or something. ---- So when should each way be used? Should I be mixing them up? I know I asked a lot of questions, but any help is appreciated. Thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by Swarmer

myClass theObject = new myClass(constructor_params);
Illegal.
Quote:

myClass* theObject = new myClass(constructor_params);
Dynamically allocates a myClass object. Stores the address of that object in a pointer called theObject.
Quote:

myClass theObject(constructor_params);
Creates a locally scoped myClass object called theObject.

Quote:

myClass* theObject(constructor_params);
Illegal.

Quote:

myClass theObject = myClass(constructor_params);
Identical in effect to 2.

Quote:

myClass* theObject = myClass(constructor_params);
Illegal.

Quote:
4+?
Any other ways to do it?
Yes, one:
myClass theObject = constructor_param
Really, though, that's just a syntax thing. There are two ways to allocate objects: statically, as in 2, or dynamically, as in 1.5. That is the major distinction you need to learn.


This is what my understanding is:

Note that X.5 all ask the same question: make a pointer to the thing or not?
My understanding is that making big classes as pointers is faster? Because when you pass them as arguments you can just pass the pointer. Also, what counts as a "big" class?) Or is it better to not use pointers and pass by reference? Am I misunderstanding some big concepts? Also, arrows are cool (->).

Re: 1:
I know that with the new keyword, I also have to remember to use delete. (I don't have to (with a few exceptions, I assume) explicitly call destructors (with or without new), do I?) I see new used a lot with pointers. Is there something to that?

I know that new dynamically allocates memory. Does that mean that I should use it for classes that have the potential to use more memory? Should that property be obvious to me when I see it?

Re: 2:
How do I know when I can do this without problems?

Re: 3:
3 and 2 are similar; I read somewhere that 3 was a safer way to do it, as sometimes 2 could be initialized incorrectly if the constructor parameter was another class' constructor or something.

----

So when should each way be used? Should I be mixing them up? I know I asked a lot of questions, but any help is appreciated. Thanks![/quote]

Share this post


Link to post
Share on other sites
Unfortunatley 1, 2.5 and 3.5 don't work the way you want them to.

new myClass returns a pointer to myClass, so you need to store it in a myClass* which is why 1 won't work.
2.5 actually creates a pointer to myClass but not an actual object of myClass. You will most likely get an error because of the constructor parameters.
3.5 create an instance of myClass but tries to store it in a myClass*, this too would give an error.

To answer your question, use 1.5 when you want to keep the object around after the function ends (we call this 'allocating on the heap') but remember to delete it when you're finished with it. Use 2 when you want the object to be destructed automatically when the function (or block) ends (called 'allocating on the stack'). 3 is essentially the same as 2 (I can really explain how it's different, I hardly understand it myself).

Share this post


Link to post
Share on other sites
Thanks for the replies!

So if I were to create an instance of a class in the broadest scope of my main function, would it matter if I created it statically or dynamically?

So creating something dynamically enables me to use it even outside of it's normal scope?

Eg. Would this be legal?


if(true)
{
myClass* theObject = new myClass(constructor_params);
}
theObject->doSomething();
delete theObject;


Thanks.

Share this post


Link to post
Share on other sites
if(true)
{
myClass* theObject = new myClass(constructor_params);
}
theObject->doSomething();
delete theObject;

This won't compile because theObject pointer doesn't exist outside the if statement.

Alternatively, this will compile but will cause a memory leak, as well as crashing your program:
myClass* theObject = 0;
if(true)
{
// any references to 'theObject' will refer to this local myClass* variable
myClass* theObject = new myClass(constructor_params);
}
theObject->doSomething(); // this is referring to the first pointer which is NULL and will crash your program
delete theObject;

Share this post


Link to post
Share on other sites
Quote:
Original post by Swarmer
Note that X.5 all ask the same question: make a pointer to the thing or not?
My understanding is that making big classes as pointers is faster? Because when you pass them as arguments you can just pass the pointer. Also, what counts as a "big" class?)


Well, the way you create the object has really not very much to do with how you pass it to functions. Creating it with new keyword makes the compiler allocate the required memory in the heap. Otherwise the object is created on the stack and is to be considered unavailable when the block that created it ends.
When you define a function you decide if parameter have to be passed as value, or as pointer (there also is reference in C++), i.e:

void myfunc(MyObj obj);

This is by value. A local copy of the object is created. Changes wont affect the original object.

void myfunc(MyObj *obj);

A pointer to the object is passed (if you created the obj on the stack, you need to get its address with the operator &). Changes apply to the original object.

Generally I use pointers (and references) with all my classes. Since a pointer is 32 bit wide (on 32 bit systems), I would say that using pointers is always faster when passing objects bigger than 4 bytes, thought you have to take into account the fact that dereferencing a pointer is a (slightly) costly operation and thus I don't use pointers for primitive types.

Quote:

Or is it better to not use pointers and pass by reference? Am I misunderstanding some big concepts? Also, arrows are cool (->).


Passing by reference is a better option (IMHO) because then you access the object exactly as it was passed by value, but AFAIK averything else is the same as with pointers. You cant pass null values though, and you cant change the address a reference points to once initialized.

Quote:

Re: 1:
I know that with the new keyword, I also have to remember to use delete. (I don't have to (with a few exceptions, I assume) explicitly call destructors (with or without new), do I?) I see new used a lot with pointers. Is there something to that?

It is not a matter what is better, but how you use the object. If you want it to last more than the current scope (without taking globals into consideration) use new. If it is a very big object, you may want to use new. For arrays of objects you will use new most of the times.
Remember that new is relatively slow, so don't use them for temporary objects unless you cant do otherwise (i.e. you call the function once at startup or similar). If you need new for temp objects (ie temporary bitmap buffers) and you call it often, consider reusing the same memory, creating it once and deleting it when you no longer need it (when the program finishes).

Quote:

I know that new dynamically allocates memory. Does that mean that I should use it for classes that have the potential to use more memory? Should that property be obvious to me when I see it?

Looking at someone else code will help you with that. Soon you will always be able to choose the better approach, often you are forced to select one of them or the other.

Quote:

Re: 3:
3 and 2 are similar; I read somewhere that 3 was a safer way to do it, as sometimes 2 could be initialized incorrectly if the constructor parameter was another class' constructor or something.

I think that the only difference is that the 3rd creates an additional temporay object, but I'm not sure it applies to construction as well as assignement. In addition, I suppose that modern compilers will take care of that and that what you get is the kind of the same code.

Share this post


Link to post
Share on other sites
Quote:
Original post by Swarmer
Thanks for the replies!

So if I were to create an instance of a class in the broadest scope of my main function, would it matter if I created it statically or dynamically?

So creating something dynamically enables me to use it even outside of it's normal scope?

Eg. Would this be legal?


if(true)
{
myClass* theObject = new myClass(constructor_params);
}
theObject->doSomething();
delete theObject;


Thanks.



myClass* theObject = 0;
if(true)
{
theObject = new myClass(constructor_params);
}
theObject->doSomething();
delete theObject;
}


Share this post


Link to post
Share on other sites
You could also store it in a reference I guess:
4.
myClass &theObject = *(new myClass(constructor_params));
//Should be fine since new wont return NULL.


This should work but is not very nice as it leaves a dangling reference.
delete &theObject;

Okay, on second thoughts, don't do this!

Share this post


Link to post
Share on other sites
lol.

Thanks for the help guys.

Out of curiosity:
So the code I posted wouldn't work because the pointer is out of scope, but the object is still in memory? Does that mean it's still accessible somehow (if I knew the address?) Or is it just a terrible idea to do this?

But yeah, I think I understand this stuff now. Thanks a bunch.

Share this post


Link to post
Share on other sites
Quote:
Original post by Swarmer
lol.

Thanks for the help guys.

Out of curiosity:
So the code I posted wouldn't work because the pointer is out of scope, but the object is still in memory? Does that mean it's still accessible somehow (if I knew the address?) Or is it just a terrible idea to do this?

But yeah, I think I understand this stuff now. Thanks a bunch.


First thing to realize is, there is no object....

Ahem...

Instances of objects are just a segment of memory, that compiler treats in a special way (offsets of member variables, vtable pointer, padding).

You can at any point tell compiler to treat something at some address as some object. Obviously, depending on what that part of memory contains, results will be from benign to horrible.

As such, the question doesn't really make sense. You can hack a particular memory section that object occupied, be it on stack or heap, but whatever values are stored there is anyone's guess.

Unlike memory managed platforms, where objects usually are some tangible entity, in C++ they are just bytes of memory carrying some meaning to a part of the code, and the instance-memory association is trivially broken.

Even more, due to several aggressive optimizations, the object, even if "allocated", might never be created, since compiler will figure out it's redundant. So even if you use an object, it never really exists.

Long story short - there's enough problems accessing properly allocated objects. Messing with de-allocated ones is simply out of the question.

Share this post


Link to post
Share on other sites
Quote:
Original post by Swarmer
lol.

Thanks for the help guys.

Out of curiosity:
So the code I posted wouldn't work because the pointer is out of scope, but the object is still in memory? Does that mean it's still accessible somehow (if I knew the address?) Or is it just a terrible idea to do this?

But yeah, I think I understand this stuff now. Thanks a bunch.

Well, technically yes, you did allocate the memory and the object is somewhere in memory.

But since you just lost the pointer, you have no idea where it could be, and since you can't delete it, you just leaked memory.

Bad mojo all round.

Share this post


Link to post
Share on other sites

This topic is 3631 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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