Re: pointer vs non-pointer
On Tue, 22 Apr 2008 11:06:54 -0400, Joseph M. Newcomer
<newcomer@flounder.com> wrote:
See below...
On Tue, 22 Apr 2008 03:51:11 -0700, worlman385@yahoo.com wrote:
On Tue, 22 Apr 2008 12:10:14 +0200, Ulrich Eckhardt
<eckhardt@satorlaser.com> wrote:
F,up to microsoft.public.vc.language, this has nothing to do with MFC.
worlman385@yahoo.com wrote:
For pointer and non-pointer initialization of an object like
MyCar mycar;
MyCar* mycar = new MyCar();
Note: the parentheses are not necessary in the second form.
I heard from other people saying if object i create must live outside
scape, then I use pointer version, else if only use object for a
limited scope, then use non-pointer version.
It depends on what type of object it is. There are objects that behave like
values (std::string, float etc) and others that behave like entities
(std::fstream, CWnd etc). Value types can be copied and so can be returned
from functions. The original object only lives inside the function, but its
value is transferred to the caller in a copy. Entity types can not be
copied, so if you need to return them from a function, you have to allocate
them dynamically.
So, if I want to return an object created in a function I better use
dynamic creation?
MyCar myfunction(){
MyCar mycar;
return mycar;
} // this is return by value
// this is more expensive as it copy whole value and return value
****
Yes. And you have to have a copy operation defined on the object, or it won't compile.
But "more expensive" is a debatable issue. If the object is created once per run of the
program, or once every five minutes, the potentially hundreds of nanoseconds required to
create the copy are not noticeable. If the return copy is created thousands of times per
second, the overhead will probably be quite noticeable. Quite often it hinges on whether
or not there is a copy constructor defined, and how complex that is to do, so it is more
an issue of programming convenience than runtime efficiency.
****
then static object creation should be used in global variables (just
like static variable) that there is "ONLY ONE" copy of the object in
the life time of an applicatoin, like follows,
CConfiguration g_Configuration;
is a global variable, then it only have a 1 copy / object in whole
application.
then that means alot of time, I must use dynamic object creation,
since alot of objects won't be needed, until some condition is meet,
then I create the object at runtime.
since I heard someone said I should use static object create like
MyCar mycar;
whenever I can, but most of the code I seen they just dynamicly create
the object using "new" operator.
===================
#include "Config.h"
//--------------------------------------------------------------
CConfiguration g_Configuration;
//--------------------------------------------------------------
CConfiguration::CConfiguration() {
Initialize();
}
//--------------------------------------------------------------
void CConfiguration::Initialize() {
//m_eControllerType = CONTROLLER_TYPE_REMOTE;
m_eControllerType = CONTROLLER_TYPE_MOUSE;
m_bFullScreen = false;
m_bProjectSplashScreen = false;
m_szComPort="COM3";
m_eRemoteType=REMOTE_TYPE_PEANUT;
switch (1) {
case 1: {
m_DisplayWidth = 1366;
m_DisplayHeight = 768;
} break;
case 2: {
m_DisplayWidth = 1024;
m_DisplayHeight = 768;
} break;
}
}
===================
MyCar* myfunction(){
MyCar* mycar = new MyCar();
return mycar;
} // this is return by reference(pointer)
// less expensive as it only return 4 byte = pointer.
****
Well, it returns a pointer. A pointer would be 8 bytes on Win64. But as already pointed
out, you will need to deal with the deletion, preferrably by the smart pointer mechanism,
****
Also for a collection of object like a LinkedList object, since it's
very expensive to return by value, i must use return by
reference(pointer):
LinkedList* myfunction(){
LinkedList* list = new LinkedList();
return list;
} // this is return by reference(pointer)
// less expensive as it only return 4 byte = pointer.
// instead of return by value to copy all element in the List
****
Whether it copies the elements of the list, or just the list header, is up to you. This
depends on the nature of the destructor of the list. Generally, you are better off
returning a pointer in this case.
****
Note that there is a subgroup of value types and that is values that are
indeed copyable but expensive to copy. Those are e.g. containers with many
elements. Being able to make this distinction can't be generalised though,
you have to look at the program in question.
Does limited scope means the object is only used in the same function
like:
void myfunction(){
MyCar mycar;
// mycar is only used inside this function
}
This means that mycar's destructor is called when the function is left (via
[implicit] return or exception).
and if mycar is used by outside scope means:
void myfunction(){
MyCar* mycar = new MyCar();
// mycar is used by other function also after function returns
mycar->AddEventListener();
// even myfunction returns,
// but mycar still need to listen for events
}
In this case, you have no choice but to create a MyCar object that still
exists after this function exits, so you need dynamic allocation. Note that
in theory, objects of static duration (globals, function-static,
class-static) could work, too, but are not as flexible.
In that case, if I used static object allocation, will it crash my
program? Will something like null pointer exception happens? as the
object get destroy automatically after function exit:
****
A static allocation is probably a bad idea. It has all kinds of nasty implications for
threading (essentially, it will always be wrong) and it means there can be at most one
instance of the object, which is rarely useful (the special case of singleton classes is
the exception to this, where the member variables are often static class members, for
example, or there is a pointer to the one-and-only heap object allocated by the singleton
class)
****
void myfunction(){
MyCar mycar = new MyCar();
// mycar is used by other function also after function returns
mycar.AddEventListener();
// even myfunction returns,
// but mycar still need to listen for events
}
****
The problem here is that you have now lost the pointer to the MyCar object, which means
that you will be unable to delete it unless there is a way for the "listener" to provide a
deletion capability, for example
void MyCar::OnLIstenEvent(...)
{
...stuff
if(event.type == Unlisten)
{
long n = InterlockedDecrement(&ListenerCount);
if(n == 0)
delete this;
}
}
where AddEventListener did an InterlockedIncrement of the count. I use the Interlocked
forms rather than ListenerCount++ and ListenerCount-- because the interlocked forms will
be thread-safe if you use multiple threads.
joe
****
I most case, I would perfer to use the static object creation:
MyCar mycar;
since I don't need to worry about delete / free object after creation.
Right, and you named the exact reasons. However, two techniques have been
invented that actually help with this:
1. garbage collection
2. smart pointers
When are the times I must use dynamic creation ( create a pointer )?
Do it when you must. Otherwise, prefer not to.
Uli
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm