By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,134 Members | 1,796 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,134 IT Pros & Developers. It's quick & easy.

Dynamically choosing what to "new"

P: n/a
Pat
Hi,

I've run into a strange problem, but one that seems like it might be
fairly common.

I have a single base class, from which several other classes are derived.
To keep the example simple, the base class is "Animal" and the derived
classes are "Cat," "Dog," and "Horse."

The base class has a pure virtual method:

virtual void GetName(std::string *s) = 0;

All the derived classes are required to implement this method and return
the appropriate string, for example:

void Dog::GetName(std::string *s)
{
*s = "Dog";
}

So when the user clicks a "Save" button, a text file is written by
calling the GetName() method on all the existing Animal objects. So the
file on disk would look something like this:

Dog, Cat, Dog, Dog, Horse, Cat

Later, when the user clicks a "Load" button, I'd like to recreate all
those animals. What's a clean way to do this? My first thought was just
to test each string with a big if-else block, like so:
while (ReadNextToken(input_string))
{
Animal *a;

if (input_string == "Dog")
{
a = new Dog;
}
else if (input_string == "Cat")
{
a = new Cat;
}
else if (input_string == "Horse")
{
a = new Horse;
}
else
{
ErrorMessage()
}
}

But that's ugly and not object-oriented at all. It's also error-prone as
I add more and more classes, because I have to remember to manually add a
new "else if" block for every new class and I have to manually ensure
that the strings match the GetName() result.

Any ideas for a better approach would be appreciated.

Thanks,
Pat
Jun 9 '07 #1
Share this Question
Share on Google+
36 Replies


P: n/a
On 9/6/07 11:22, in article Xn******************@140.99.99.130, "Pat"
<no**@none.nonewrote:
Any ideas for a better approach would be appreciated.
You might want to investigate the Factory design pattern.

--
Regards,
Steve

"...which means he created the heaven and the earth... in the DARK! How good
is that?"

Jun 9 '07 #2

P: n/a
Pat wrote:
Hi,

I've run into a strange problem, but one that seems like it might be
fairly common.
It is common.

I don't know of any other generic factory implementations but the one in
Austria C++ will allow you to register a number of different factories
(named Dog, Cat etc) and simply request construction on an appropriate one.
#include "at_factory.h"

class Animal
{

};

int main( int argc, char ** argv )
{

if ( argc == 2 )
{

Animal * animal = at::FactoryRegister<
Animal, at::DKy
>::Get().Create( argv[1] )();
// the Create method takes a few other arguments
// one that tells it to throw on failure
if ( ! animal )
{
return 1;
}

}
};

// this stuff below can be in any source file or even DLL/DSO

struct Dog : Animal
{
};

// AT_MakeFactory0P is a macro that "registers" a factory
// for Dog under the key "Dog" over it's interface Animal
// using a key type of at::DKy - you could use std::string
// here if you wanted to.
AT_MakeFactory0P( "Dog", Dog, Animal, at::DKy );
struct Cat : Animal
{
};

AT_MakeFactory0P( "Dog", Cat, Animal, at::DKy );
Careful that you make sure the factory object files are linked in.
That's the usual source of frustration using this. There are a couple
of tools which help you do that but it's the only issue.
Jun 9 '07 #3

P: n/a
On Jun 9, 12:22 pm, Pat <n...@none.nonewrote:
I've run into a strange problem, but one that seems like it might be
fairly common.
I have a single base class, from which several other classes are derived.
To keep the example simple, the base class is "Animal" and the derived
classes are "Cat," "Dog," and "Horse."
The base class has a pure virtual method:
virtual void GetName(std::string *s) = 0;
All the derived classes are required to implement this method and return
the appropriate string, for example:
void Dog::GetName(std::string *s)
{
*s = "Dog";
}
Not related to your problem, but is there any reason for passing
a poniter to a string, and not simply returning a string.
So when the user clicks a "Save" button, a text file is written by
calling the GetName() method on all the existing Animal objects. So the
file on disk would look something like this:
Dog, Cat, Dog, Dog, Horse, Cat
Later, when the user clicks a "Load" button, I'd like to recreate all
those animals. What's a clean way to do this?
The usual situation is some sort of registry with either
pointers to functions, or pointers to an abstract Factory
object. Using the abstract factory object method, this might
look like:

class Factory
{
public:
virtual ~Factory() {}
virtual Animal* create() const = 0 ;

protected:
explicit Factory( std::string const& name ) ;
} ;
typedef std::map< std::string, Factory const* >
FactoryMap ;
FactoryMap factoryMap ;

Factory::Factory(
std::string const& name )
{
FactoryMap::iterator
elem = factoryMap.find( name ) ;
assert( elem == factoryMap.end() ) ;
factoryMap.insert( FactoryMap::value_type( name, this ) ) ;
}

template< typename T >
class ConcreteFactory : public Factory
{
public:
explicit ConcreteFactory( std::string const& name )
: Factory( name )
{
}

virtual Animal* create() const
{
return new T ;
}
} ;

Given that, you just declare a static instance of a factory for
each type you're interested in. (Watch out for order of
initialization issues, though. In practice, I usually make the
map a singleton.)

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 9 '07 #4

P: n/a
Pat
James Kanze <ja*********@gmail.comwrote in
news:11**********************@p77g2000hsh.googlegr oups.com:
> void Dog::GetName(std::string *s)
{
*s = "Dog";
}

Not related to your problem, but is there any reason for passing
a poniter to a string, and not simply returning a string.

Yes, passing a pointer is more efficient because it avoids copying the
entire object onto the stack. I try to always pass pointers or references,
unless the parameter is small (e.g. int). In this one simplified case it
might not make much difference, since the "=" operator is going to
basically perform a copy anyway. But for real world functions, it's a good
idea.
[code snipped]
Given that, you just declare a static instance of a factory for
each type you're interested in. (Watch out for order of
initialization issues, though. In practice, I usually make the
map a singleton.)

Thank you, this is exactly what I needed. And thanks to the others who
also suggested the "factory" design pattern. I am educated! I must have
spaced out on the day that was covered in my abstract data structures
class. Thanks again.

Pat
Jun 10 '07 #5

P: n/a
On 2007-06-09 22:17:04 -0700, Pat <no**@none.nonesaid:
James Kanze <ja*********@gmail.comwrote in
news:11**********************@p77g2000hsh.googlegr oups.com:
>>void Dog::GetName(std::string *s)
{
*s = "Dog";
}

Not related to your problem, but is there any reason for passing
a poniter to a string, and not simply returning a string.


Yes, passing a pointer is more efficient because it avoids copying the
entire object onto the stack.
Are you sure about that? Many compilers will do return-value
optimization. Additionally, copying an instance of std::string may be a
lot less expensive than you think it is (for instance, many
implementations are copy-on-write).

The morals of the story: don't optimize without profiling, and all
generalizations are wrong :)

--
Clark S. Cox III
cl*******@gmail.com

Jun 10 '07 #6

P: n/a
On Jun 10, 7:17 am, Pat <n...@none.nonewrote:
James Kanze <james.ka...@gmail.comwrote innews:11**********************@p77g2000hsh.google groups.com:
void Dog::GetName(std::string *s)
{
*s = "Dog";
}
Not related to your problem, but is there any reason for passing
a poniter to a string, and not simply returning a string.
Yes, passing a pointer is more efficient because it avoids copying the
entire object onto the stack.
More efficient in what? It means that the user has to declare
extra objects, and manage them, which is a definite loss of
programmer efficiency. So until you've measured a problem, it's
pure stupitidy to not use a return value. Especially because it
is just as often more efficient to use the return value; there
is no hard and fast rule.
I try to always pass pointers or references,
unless the parameter is small (e.g. int).
Which is just stupid.
In this one simplified case it
might not make much difference, since the "=" operator is going to
basically perform a copy anyway. But for real world functions, it's a good
idea.
Nonsense.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 10 '07 #7

P: n/a

"James Kanze" <ja*********@gmail.comwrote in message
news:11**********************@p77g2000hsh.googlegr oups.com...
On Jun 9, 12:22 pm, Pat <n...@none.nonewrote:
All the derived classes are required to implement this method and return
the appropriate string, for example:
void Dog::GetName(std::string *s)
{
*s = "Dog";
}
"Not related to your problem, but is there any reason for passing
a poniter to a string, and not simply returning a string."

Or better still, a reference so null-checking can be eliminated.

But, my preference is that "get functions" return what they are getting, and
not prepending "get" to the function name, and Name() seems better as a base
class non-virtual function:

const char* Animal::Name()
{
return name; // ptr to a char array containing "Dog"
}

or (for those who prefer "fat C++" over "veneer C++" style coding):
// note that reference return allows this function to be used as a setter
also
// if it wasn't const but in this case of usage setting is not appropriate
for the
// data member which will be initialized at construction somehow.
//
const std::string& Animal::Name()
{
return name; // ptr to a string containing "Dog"
}

I don't see any reason to hide-away "Dog" as a string literal in one of the
methods (does anyone else?). It's data, so why make it "code-like"?

(LOL, I was just going to post about preferably passing in references rather
than pointers, and then I started thinking a bit about the actual context
and design).

John


Jun 11 '07 #8

P: n/a

"Clark Cox" <cl*******@gmail.comwrote in message
news:2007060922265716807-clarkcox3@gmailcom...
On 2007-06-09 22:17:04 -0700, Pat <no**@none.nonesaid:
>James Kanze <ja*********@gmail.comwrote in
news:11**********************@p77g2000hsh.googleg roups.com:
>>>void Dog::GetName(std::string *s)
{
*s = "Dog";
}

Not related to your problem, but is there any reason for passing
a poniter to a string, and not simply returning a string.


Yes, passing a pointer is more efficient because it avoids copying the
entire object onto the stack.

Are you sure about that? Many compilers will do return-value optimization.
Additionally, copying an instance of std::string may be a lot less
expensive than you think it is (for instance, many implementations are
copy-on-write).

The morals of the story: don't optimize without profiling, and all
generalizations are wrong :)
Note that "copy-on-write" _is_ an optimization.

John
Jun 11 '07 #9

P: n/a

"James Kanze" <ja*********@gmail.comwrote in message
news:11**********************@q75g2000hsh.googlegr oups.com...
On Jun 10, 7:17 am, Pat <n...@none.nonewrote:
James Kanze <james.ka...@gmail.comwrote
innews:11**********************@p77g2000hsh.google groups.com:
I try to always pass pointers or references,
unless the parameter is small (e.g. int).
"Which is just stupid."

My rule of thumb is "pass a reference when you can, pass a pointer when you
have to" as arguments to functions. Copy-on-write may be a technique for
severely constrained platforms rather than a general technique to be used
everywhere (an exercise in futility?).

John
Jun 11 '07 #10

P: n/a
JohnQ wrote:
....
Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.

Also, as a side note, it appears that the std::string interface is too
loose to be able to provide an optimal and flawless copy on write
optimization. GCC is at least planning to abandon its copy on write
std::sting impl.
Jun 11 '07 #11

P: n/a
JohnQ wrote:
"James Kanze" <ja*********@gmail.comwrote in message
news:11**********************@q75g2000hsh.googlegr oups.com...
On Jun 10, 7:17 am, Pat <n...@none.nonewrote:
>James Kanze <james.ka...@gmail.comwrote
innews:11**********************@p77g2000hsh.googl egroups.com:
>I try to always pass pointers or references,
unless the parameter is small (e.g. int).

"Which is just stupid."

My rule of thumb is "pass a reference when you can, pass a pointer when you
have to" as arguments to functions. Copy-on-write may be a technique for
severely constrained platforms rather than a general technique to be used
everywhere (an exercise in futility?).
What exact point are you trying to make with COW ? It seems like it has
very common usage..
Jun 11 '07 #12

P: n/a

"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
>"James Kanze" <ja*********@gmail.comwrote in message
news:11**********************@q75g2000hsh.googleg roups.com...
On Jun 10, 7:17 am, Pat <n...@none.nonewrote:
>>James Kanze <james.ka...@gmail.comwrote
innews:11**********************@p77g2000hsh.goog legroups.com:
>>I try to always pass pointers or references,
unless the parameter is small (e.g. int).

"Which is just stupid."

My rule of thumb is "pass a reference when you can, pass a pointer when
you have to" as arguments to functions. Copy-on-write may be a technique
for severely constrained platforms rather than a general technique to be
used everywhere (an exercise in futility?).

What exact point are you trying to make with COW ? It seems like it has
very common usage..
"don't use it if you don't have to". I don't think it has a place at lower
level code for general usage because it complicates things unnecessarily.
COW looks like one of those "oh, look what neat things one can do with C++"
things that is general knowledge but should be used judiciously. That is to
say that it should probably be avoided (pass a reference instead and "go
ahead and make a copy" when you need to because chances are that CPU power
and memory is not an issue, but code maintenance and reliability is). (Ref:
Keep It Simple Stupid, but not "simply stupid" or "stupidly simple" either).

I couldn't find the link to the site that discussed the COW issues
(especially in an MT environment) in depth, but google is your friend, and
maybe you can find something similar.

John
Jun 11 '07 #13

P: n/a

"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
...
>Note that "copy-on-write" _is_ an optimization.

Yah - but it's an optimization made by the compiler not be me.
No, no, it's coded into the string class (user-level stuff).
Also, as a side note, it appears that the std::string interface is too
loose to be able to provide an optimal and flawless copy on write
optimization. GCC is at least planning to abandon its copy on write
std::sting impl.
I did so in my own string class a few years ago also after reading a
discussion about the non-necessity of it and the potential problems in a
multi-threaded environment.

John
Jun 11 '07 #14

P: n/a
JohnQ wrote:
"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
>JohnQ wrote:
...
>>Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.

No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above. The
issue here is WHO does the optimization not that it is done or not.
Jun 11 '07 #15

P: n/a
On Jun 11, 3:08 am, Gianni Mariani <gi3nos...@mariani.wswrote:
JohnQ wrote:
"James Kanze" <james.ka...@gmail.comwrote in message
news:11**********************@q75g2000hsh.googlegr oups.com...
On Jun 10, 7:17 am, Pat <n...@none.nonewrote:
James Kanze <james.ka...@gmail.comwrote
innews:11**********************@p77g2000hsh.google groups.com:
I try to always pass pointers or references,
unless the parameter is small (e.g. int).
"Which is just stupid."
My rule of thumb is "pass a reference when you can, pass a pointer whenyou
have to" as arguments to functions. Copy-on-write may be a technique for
severely constrained platforms rather than a general technique to be used
everywhere (an exercise in futility?).
What exact point are you trying to make with COW ? It seems like it has
very common usage..
It's extremely difficult to get both right and with acceptable
performance in a multithreaded environment. For
std::basic_string, I only know of two COW implementations: Sun
CC is unacceptably slow, and g++ has bugs. Admittedly, a large
part of the problem here is that std::basic_string has a
particularly pernicious interface. But I find that while I made
extensive use of COW when I started C++, some 15 years ago, I
rarely if ever use it today. Improvements in machine speed, and
above all allocation algorithms, coupled with the widespread use
of multithreading, have made it largely obslete today.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 11 '07 #16

P: n/a
Pat
Interesting thread... The efficiency of the "GetName()" method wasn't
really a concern, because it was just a function I made up to illustrate my
problem.

But in response to the comments about passing by addres vs passing by
reference vs passing by value, I really don't understand the arguments
against passing pointers as a parameter. It's guaranteed to be fast,
without requiring tricky compiler optimizations. And if you do it as a
rule, you don't really have a problem with it "adding complexity."

But complexity issues aside (I don't really see what they are, anyway), as
I initially said, in "real world" functions, I don't see a way around
passing pointers. If you've got a function that takes several large
objects as parameters, accesses various members of each, then returns some
value as a result, I think you'd be crazy to pass in the objects as copies.

I've really never given it much thought. It has just been an accepted rule
of thumb at places where I've worked -- mainly game development, where
performance is crucial.

I'm willing to believe that a smart compiler might be able to optimize
pass-by-value to be *as good* as pass-by-reference, in some cases, but I
don't really see what you gain, besides maybe a longer compile time.
Jun 11 '07 #17

P: n/a
Pat wrote:
Interesting thread... The efficiency of the "GetName()" method wasn't
really a concern, because it was just a function I made up to illustrate my
problem.

But in response to the comments about passing by addres vs passing by
reference vs passing by value, I really don't understand the arguments
against passing pointers as a parameter. It's guaranteed to be fast,
without requiring tricky compiler optimizations. And if you do it as a
rule, you don't really have a problem with it "adding complexity."
It may be less efficient and more complex to pass a string by pointer.
Consider the case where you want to initialise a string from an object
method, so your getName():

std::string name;
object.getName( &name );

now if getName() where declared as

std::string& getName() const { return someName; }

one could simply write

std::string name( object.getName );

I can't think of any situation where passing a string by pointer would
be the preferred solution. Passing by (const) reference should be used
instead.
But complexity issues aside (I don't really see what they are, anyway), as
I initially said, in "real world" functions, I don't see a way around
passing pointers. If you've got a function that takes several large
objects as parameters, accesses various members of each, then returns some
value as a result, I think you'd be crazy to pass in the objects as copies.
Pass by (const) reference.
I've really never given it much thought. It has just been an accepted rule
of thumb at places where I've worked -- mainly game development, where
performance is crucial.

I'm willing to believe that a smart compiler might be able to optimize
pass-by-value to be *as good* as pass-by-reference, in some cases, but I
don't really see what you gain, besides maybe a longer compile time.
The key to returning by value is the common optimisation Return Value
Optimisation. RVO makes the example getName() above very efficient.

--
Ian Collins.
Jun 11 '07 #18

P: n/a
Ian Collins wrote:
Pat wrote:
>Interesting thread... The efficiency of the "GetName()" method wasn't
really a concern, because it was just a function I made up to illustrate my
problem.

But in response to the comments about passing by addres vs passing by
reference vs passing by value, I really don't understand the arguments
against passing pointers as a parameter. It's guaranteed to be fast,
without requiring tricky compiler optimizations. And if you do it as a
rule, you don't really have a problem with it "adding complexity."
It may be less efficient and more complex to pass a string by pointer.
Consider the case where you want to initialise a string from an object
method, so your getName():

std::string name;
object.getName( &name );

now if getName() where declared as

std::string& getName() const { return someName; }

one could simply write

std::string name( object.getName );
std::string name( object.getName() );

--
Ian Collins.
Jun 11 '07 #19

P: n/a

"Pat" <no**@none.nonewrote in message
news:Xn******************@140.99.99.130...
Interesting thread... The efficiency of the "GetName()" method wasn't
really a concern, because it was just a function I made up to illustrate
my
problem.

But in response to the comments about passing by addres vs passing by
reference vs passing by value, I really don't understand the arguments
against passing pointers as a parameter.
I don't either. Passing a pointer is fine, but you'll probably have to do
precondition checking for null with a pointer while for a reference that is
eliminated because references cannot be null. (I wonder if the standard will
eventually incorporate null references?).
It's guaranteed to be fast,
without requiring tricky compiler optimizations. And if you do it as a
rule, you don't really have a problem with it "adding complexity."

But complexity issues aside (I don't really see what they are, anyway), as
I initially said, in "real world" functions, I don't see a way around
passing pointers. If you've got a function that takes several large
objects as parameters, accesses various members of each, then returns some
value as a result, I think you'd be crazy to pass in the objects as
copies.
Agreed, but references were created for that very scenario I think. Nothing
wrong with pointers though either.
I've really never given it much thought. It has just been an accepted
rule
of thumb at places where I've worked -- mainly game development, where
performance is crucial.

I'm willing to believe that a smart compiler might be able to optimize
pass-by-value to be *as good* as pass-by-reference, in some cases, but I
don't really see what you gain, besides maybe a longer compile time.
I don't think most will make a case for passing object instances by value.

John
Jun 11 '07 #20

P: n/a

"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
>"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
>>JohnQ wrote:
...
Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.

No, no, it's coded into the string class (user-level stuff).

I lumped the STL as part of the "compiler" in the statement above.
I know, that's why I posted: it's incorrect.
The issue here is WHO does the optimization not that it is done or not.
Oh, I thought it was whether COW is worthwhile or not.

John
Jun 11 '07 #21

P: n/a
JohnQ wrote:
"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
>JohnQ wrote:
>>"Gianni Mariani" <gi*******@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
...
Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.
No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above.

I know, that's why I posted: it's incorrect.
Debatable.
>
>The issue here is WHO does the optimization not that it is done or not.

Oh, I thought it was whether COW is worthwhile or not.
COW is an optimization. It may or may nor be worthwhile, like all
optimizations it depends.
Jun 11 '07 #22

P: n/a

On 6/11/07 4:37 PM, in article Z0***************@newssvr19.news.prodigy.net,
"JohnQ" <jo***********************@yahoo.comwrote:
"Pat" <no**@none.nonewrote in message
news:Xn******************@140.99.99.130...
>Interesting thread... The efficiency of the "GetName()" method wasn't
really a concern, because it was just a function I made up to illustrate
my
problem.

But in response to the comments about passing by addres vs passing by
reference vs passing by value, I really don't understand the arguments
against passing pointers as a parameter.

I don't either. Passing a pointer is fine, but you'll probably have to do
precondition checking for null with a pointer while for a reference that is
eliminated because references cannot be null. (I wonder if the standard will
eventually incorporate null references?).
The argument is against passing any parameter at all to a routine that needs
no input. In particular a class object's GetName() method requires no data
from the callee in order to return the object's name, and therefore has no
reason to accept a parameter.
>It's guaranteed to be fast,
without requiring tricky compiler optimizations. And if you do it as a
rule, you don't really have a problem with it "adding complexity."
But the unneeded parameter does add complexity - which you may not mind -
but what about other programmers who might be responsible for maintaining
this code in the future? Are they likely to welcome anything that makes this
code (which after all they did not write and are not familiar with) any more
difficult to understand?
>But complexity issues aside (I don't really see what they are, anyway), as
I initially said, in "real world" functions, I don't see a way around
passing pointers. If you've got a function that takes several large
objects as parameters, accesses various members of each, then returns some
value as a result, I think you'd be crazy to pass in the objects as
copies.
The added complexity is simple to identify: there is a function that should
not need a parameter - but that requires one nonetheless. So, before writing
code to call this method, the programmer has to figure out what this
mysterious parameter does - and how to use it in ways that will satisfy the
function's preconditions. And all of this work (and the opportunities for
mistakes it creates) provides no benefit that might justify these costs.
Agreed, but references were created for that very scenario I think. Nothing
wrong with pointers though either.
There are numerous reasons to avoid pointers as I/O parameters. For one, a
pointer might be NULL - a possibility that the caller or callee may not be
prepared to handle. Pointers are also likely raise issues of allocation and
deallocation as well as object lifetimes - all issues that may be difficult
to coordinate and debug.
>I've really never given it much thought. It has just been an accepted
rule
of thumb at places where I've worked -- mainly game development, where
performance is crucial.

I'm willing to believe that a smart compiler might be able to optimize
pass-by-value to be *as good* as pass-by-reference, in some cases, but I
don't really see what you gain, besides maybe a longer compile time.

I don't think most will make a case for passing object instances by value.
Clearly whenever the object instance itself is the same size or smaller than
a pointer or a reference to that object would be - it makes sense to pass
the object by value. Pointers themselves are an obvious example of this
principle. Passing a pointer to a pointer (or a pointer by const reference)
for efficiency reasons would make little sense - since it is clear in the
case of a pointer object that no additional efficiency will be attained by
any calling convention other than passing the pointer by value.

And what holds for a pointer type also applies equally as well to any object
the same size or smaller than a pointer - built-in integral types for
example usually fall into this category. In fact passing a short by
reference or pointer is much more likely to be less efficient than passing
the short by value. In fact, boost even has a library "call_traits" that
pretty much automates the selection of a parameter's calling convention for
optimal efficiency based on its type.

Greg
Jun 12 '07 #23

P: n/a

"Greg Herlihy" <gr****@pacbell.netwrote in message
news:C2******************@pacbell.net...
>
On 6/11/07 4:37 PM, in article
Z0***************@newssvr19.news.prodigy.net,
"JohnQ" <jo***********************@yahoo.comwrote:
>"Pat" <no**@none.nonewrote in message
news:Xn******************@140.99.99.130...
>>Interesting thread... The efficiency of the "GetName()" method wasn't
really a concern, because it was just a function I made up to illustrate
my
problem.

But in response to the comments about passing by addres vs passing by
reference vs passing by value, I really don't understand the arguments
against passing pointers as a parameter.

I don't either. Passing a pointer is fine, but you'll probably have to do
precondition checking for null with a pointer while for a reference that
is
eliminated because references cannot be null. (I wonder if the standard
will
eventually incorporate null references?).

The argument is against passing any parameter at all to a routine that
needs
no input.
No, I don't think that is the topic at all, though I did bring up that
design issue in a previous post in this thread. The OP was just asking in
general about objects passed to a function and why "pointers to such are
bad".
>Agreed, but references were created for that very scenario I think.
Nothing
wrong with pointers though either.

There are numerous reasons to avoid pointers as I/O parameters. For one, a
pointer might be NULL
That's been mentioned in a prior post (by me).
- a possibility that the caller or callee may not be
prepared to handle. Pointers are also likely raise issues of allocation
and
deallocation as well as object lifetimes - all issues that may be
difficult
to coordinate and debug.
The issue is the cost of copying objects if they are passed in by value.
Which naturally leads in to a discussion about copy-on-write.
>I don't think most will make a case for passing object instances by
value.

Clearly whenever the object instance itself is the same size or smaller
than
a pointer or a reference to that object would be - it makes sense to pass
the object by value.
That's been noted already by the OP. The "understood" theme was the passing
of objects (or at least I certainly would not assume that posters here are
in the first day of programming class! Geez.). You really should read all
the prior posts in a thread before you jump in the middle of one and rehash
that which has already been put forth.

John
Jun 12 '07 #24

P: n/a
On Jun 11, 4:29 pm, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message

news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
...
Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.
No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above.

I know, that's why I posted: it's incorrect.
No - since both the C++ compiler and the Standard Library belong to
the "implementation" it could be possible for a C++ compiler to
"implement" the Standard Library by, say, emitting appropriate machine
code whenever it compiles user code that makes use of the Standard
Library's facilities. In short, there is no requirement that the
Standard C++ Library be written in C++ or even that it exist as a code
"library" at all. So while it may seem odd to think of the STL and the
C++ compiler as two sides of the same code - essentially they are.

Greg
Jun 12 '07 #25

P: n/a

"Greg Herlihy" <gr****@pacbell.netwrote in message
news:11**********************@i38g2000prf.googlegr oups.com...
On Jun 11, 4:29 pm, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
>"Gianni Mariani" <gi3nos...@mariani.wswrote in message

news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
...
Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.
>No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above.

I know, that's why I posted: it's incorrect.

No - since both the C++ compiler and the Standard Library belong to
the "implementation" it could be possible for a C++ compiler to
"implement" the Standard Library by, say, emitting appropriate machine
code whenever it compiles user code that makes use of the Standard
Library's facilities. In short, there is no requirement that the
Standard C++ Library be written in C++ or even that it exist as a code
"library" at all. So while it may seem odd to think of the STL and the
C++ compiler as two sides of the same code - essentially they are.
I'm not buying it. A freestanding implementation need not supply library
functionality at all, so it's optional. Standard Template LIBRARY. Until it
becomes common practice to embed STL functionality into compilers, I say
calling STL a part of the compiler is incorrect. Part of the language spec,
yes. Part of any known compiler, no.

John
Jun 12 '07 #26

P: n/a
On Jun 12, 1:29 am, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
...
Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.
No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above.
I know, that's why I posted: it's incorrect.
In what sense? As far as the standard is concerned, the
standard library is part of the language. You get it with the
compiler, and use it as if it were part of the compiler. The
compiler is aware of certain parts of it, at least (e.g.
type_info, or operator new()). Most implementations do allow
replacing a significant part, at least if it is done as a block,
but that's an extension, and you normally think of the standard
library (plus a number of system libraries, such as the Posix
interface) as being part of the "implementation", in other
words, the compiler. You don't worry about how
std::basic_string is implemented, you just use it.

--
James Kanze (GABI Software, from CAI) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 12 '07 #27

P: n/a
On Jun 12, 12:39 am, Ian Collins <ian-n...@hotmail.comwrote:

[...]
I can't think of any situation where passing a string by
pointer would be the preferred solution.
When it's optional, and you want to allow for a null pointer in
the case where it isn't provided:-).

There are, in fact, a number of different conventions as to when
to use pointers, and when to use references. At one extreme,
there are people who practically never use non-const references;
if the object is to be modified by the function, they want this
immediately visible at the call site (and thus require that the
caller explicitly take the address). At the other, a lot of
people use references except when it is impossible (e.g. because
they also need a null pointer). In between, I've encountered
more than a few places where the rule was to use a pointer if
the function did anything "pointer-like" with it; basically, if
it deleted the object, or stored the address somewhere for later
use.

What I've not seen very often is using a pointer for a pure out
parameter; generally, a return value is to be preferred. Most
of the time, inout uses a reference, although as mentionned
above, there are people who disagree. And everywhere I've seen,
pure in parameters are by value or by const reference, unless
they're optional, and a null pointer is used to indicate their
absense.

--
James Kanze (GABI Software, from CAI) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 12 '07 #28

P: n/a
On Jun 12, 1:37 am, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:

[...]
I don't think most will make a case for passing object
instances by value.
The standard library does it all the time: iterators,
predicates, comparison operators...

John Potter once made the (valid) argument that passing by const
reference, instead of passing by value, is an optimization, and
as such, should only be used when the profiler says it is
necessary. I think that most people are a little less rigorous
about it than that, and will accept pass by const reference if
the object is potentially expensive to copy (in the sense that
it has, for example, an open size, and so must involve dynamic
allocation, for example). In practice, I'd consider it an
acceptable rule to pass containers by const reference, and
everything else by value.

This only applies, of course, to in parameters. In general, it
is desirable to use only in parameters, and to have at most a
single out parameter, which is returned by value as a return
value. But this isn't always pratical; sometimes, you need two
out parameters, or an inout (rather than separate in and out
parameters); in such cases, non-const references are the most
generally approved solution (although some people prefer
pointers, making the fact that the function modifies the object
explicit at the call site).

The problem with using references or pointers for out
parameters, of course, is that the client code must declare (and
construct, if the object has class type) an instance at the call
site, before he has anything to put in it. If getS() is a
function which returns a string (has a single out parameter),
something like:
std::string result ;
getS( result ) ;
is a lot more painful than just:
std::string result( getS() ) ;
Depending on the implementation, it's likely to be slower as
well.

--
James Kanze (GABI Software, from CAI) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 12 '07 #29

P: n/a

"James Kanze" <ja*********@gmail.comwrote in message
news:11**********************@i13g2000prf.googlegr oups.com...
On Jun 12, 1:29 am, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
...
Note that "copy-on-write" _is_ an optimization.
Yah - but it's an optimization made by the compiler not be me.
No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above.
I know, that's why I posted: it's incorrect.
"In what sense? As far as the standard is concerned, the
standard library is part of the language. You get it with the
compiler, and use it as if it were part of the compiler. The
compiler is aware of certain parts of it, at least (e.g.
type_info, or operator new()). Most implementations do allow
replacing a significant part, at least if it is done as a block,
but that's an extension, and you normally think of the standard
library (plus a number of system libraries, such as the Posix
interface) as being part of the "implementation", in other
words, the compiler. You don't worry about how
std::basic_string is implemented, you just use it."

Correction: that is how YOU perceive it. I don't even think of a vendor's
combination as an entity: I may use JohnQ Templates rather than the STL that
comes with it. When someone say's "compiler", I indeed think the executable
that does the compiling of source code into machine code or assembly. In the
other case, I'd use "development environment", VC++ or similar terminology.

John
Jun 12 '07 #30

P: n/a
On 12 Jun, 12:40, "JohnQ" <johnqREMOVETHISprogram...@yahoo.comwrote:
"James Kanze" <james.ka...@gmail.comwrote in message

news:11**********************@i13g2000prf.googlegr oups.com...
On Jun 12, 1:29 am, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
>"Gianni Mariani" <gi3nos...@mariani.wswrote in message
I lumped the STL as part of the "compiler" in the statement above.
I know, that's why I posted: it's incorrect.

"In what sense? As far as the standard is concerned, the
standard library is part of the language. You get it with the
compiler, and use it as if it were part of the compiler. The
compiler is aware of certain parts of it, at least (e.g.
type_info, or operator new()). Most implementations do allow
replacing a significant part, at least if it is done as a block,
but that's an extension, and you normally think of the standard
library (plus a number of system libraries, such as the Posix
interface) as being part of the "implementation", in other
words, the compiler. You don't worry about how
std::basic_string is implemented, you just use it."

Correction: that is how YOU perceive it. I don't even think of a vendor's
combination as an entity: I may use JohnQ Templates rather than the STL that
comes with it. When someone say's "compiler", I indeed think the executable
that does the compiling of source code into machine code or assembly. In the
other case, I'd use "development environment", VC++ or similar terminology.
I don't think "development environment" is the right term. To many
people that will imply additional concepts like debuggers and other
tools that are beyond the scope of the C++ standard and I don't think
that's what the posts you are responding to were talking about at all.

The concept being discussed is the implementation of all the
requirements of ISO standard number 14882 (whatever the precise title
of the document is) and nothing else. That's a well defined and easily
understood concept. To be able to refer to that concept in
conversation, it is useful to give it a name - my preference is to
call it "the implementation". I happen to be used to implementations
of ISO 14882 that are provided in two basic parts: 1) an executable
that turns source code into machine code and 2) files of source code
that implement the standard library parts of ISO 14882. And I happen
to be used to the first part (the executable) being called a compiler.
So to also use the name "compiler" to refer to the concept of the
whole implementation of ISO 14882 (the sum of parts 1 and 2 above)
sits slightly uncomfortably with me because using the same word to
mean two different things is generally a bad idea.

However, I recognise that my discomfort only comes about through my
knowledge of *how* the requirements of ISO 14882 have been implemented
in the implementations I am used to (two separate parts as above). And
since the existence of two separate parts is an implementation detail,
as an engineer I should be ready and able to ignore it. So if other
peple are happy to use "compiler" as the name for the concept that I
prefer to call "implementation" that's fine by me because I know
exactly what they are talking about.

But the important thing is to all be talking about the same thing and
I think the concept is clear even if the name for it is contentious.

Gavin Deane

Jun 12 '07 #31

P: n/a
On Jun 12, 1:40 pm, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"James Kanze" <james.ka...@gmail.comwrote in message
news:11**********************@i13g2000prf.googlegr oups.com...
On Jun 12, 1:29 am, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
>"Gianni Mariani" <gi3nos...@mariani.wswrote in message
>>news:46***********************@per-qv1-newsreader-01.iinet.net.au...
>>JohnQ wrote:
>>...
>>>Note that "copy-on-write" _is_ an optimization.
>>Yah - but it's an optimization made by the compiler not be me.
>No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above.
I know, that's why I posted: it's incorrect.
"In what sense? As far as the standard is concerned, the
standard library is part of the language. You get it with the
compiler, and use it as if it were part of the compiler. The
compiler is aware of certain parts of it, at least (e.g.
type_info, or operator new()). Most implementations do allow
replacing a significant part, at least if it is done as a block,
but that's an extension, and you normally think of the standard
library (plus a number of system libraries, such as the Posix
interface) as being part of the "implementation", in other
words, the compiler. You don't worry about how
std::basic_string is implemented, you just use it."
Correction: that is how YOU perceive it.
Correction: it's how the language is defined. Every language
I've ever used is defined in this way.
I don't even think of a vendor's combination as an entity: I
may use JohnQ Templates rather than the STL that comes with
it.
No you may not. If it works, it's an extension on the part of
the compiler. And it doesn't always work.
When someone say's "compiler", I indeed think the executable
that does the compiling of source code into machine code or
assembly. In the other case, I'd use "development
environment", VC++ or similar terminology.
That's a more or less frequent distinction. We speak of
compilers, linkers, library components, etc. to refer to parts
of the implementation. But the implementation is a monolith;
you can't mix and match different parts. And the distinctions
are blurred; most systems today will generate code at link time,
given certain options, and there is a definition interaction
between the library and the language in certain cases, such as
std::type_info. In the past, C compilers regularly "knew" the
semantics of certain standard functions (and generated them
inline), and it's to be expected that in the future, C++
compilers will know the details things like std::vector.

The standard is very clear about this. There's really no room
for discussion.

--
James Kanze (GABI Software) mailto:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 13 '07 #32

P: n/a

"James Kanze" <ja*********@gmail.comwrote in message
news:11********************@z28g2000prd.googlegrou ps.com...
On Jun 12, 1:40 pm, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"James Kanze" <james.ka...@gmail.comwrote in message
news:11**********************@i13g2000prf.googlegr oups.com...
On Jun 12, 1:29 am, "JohnQ" <johnqREMOVETHISprogram...@yahoo.com>
wrote:
"Gianni Mariani" <gi3nos...@mariani.wswrote in message
news:46***********************@per-qv1-newsreader-01.iinet.net.au...
JohnQ wrote:
>"Gianni Mariani" <gi3nos...@mariani.wswrote in message
>>news:46***********************@per-qv1-newsreader-01.iinet.net.au...
>>JohnQ wrote:
>>...
>>>Note that "copy-on-write" _is_ an optimization.
>>Yah - but it's an optimization made by the compiler not be me.
>No, no, it's coded into the string class (user-level stuff).
I lumped the STL as part of the "compiler" in the statement above.
I know, that's why I posted: it's incorrect.
"In what sense? As far as the standard is concerned, the
standard library is part of the language. You get it with the
compiler, and use it as if it were part of the compiler. The
compiler is aware of certain parts of it, at least (e.g.
type_info, or operator new()). Most implementations do allow
replacing a significant part, at least if it is done as a block,
but that's an extension, and you normally think of the standard
library (plus a number of system libraries, such as the Posix
interface) as being part of the "implementation", in other
words, the compiler. You don't worry about how
std::basic_string is implemented, you just use it."
Correction: that is how YOU perceive it.
"Correction: it's how the language is defined. Every language
I've ever used is defined in this way."

I'm not big on other people's definitions (especially when they're wrong!).
Hehe. I hear what you're saying though. When I switched from Borland to MS I
switched to using the MS libraries also because they are tied to the vendors
compiler. I haven't noticed anything in the other direction though. That
would be a serious matter (there should be a warning on the box or
something).

Whether I can get away from using all of the standard headers/libraries or
not is yet to be determined. I think it's a worthwhile pursuit though.
Moreso now after the info you presented.
I don't even think of a vendor's combination as an entity: I
may use JohnQ Templates rather than the STL that comes with
it.
"No you may not. If it works, it's an extension on the part of
the compiler. And it doesn't always work."

Yes I may, and I do. Honestly, I'm hardly worried about being
standard-compliant. Indeed, that's like being put in a straitjacket.
When someone say's "compiler", I indeed think the executable
that does the compiling of source code into machine code or
assembly. In the other case, I'd use "development
environment", VC++ or similar terminology.
"That's a more or less frequent distinction. We speak of
compilers, linkers, library components, etc. to refer to parts
of the implementation. But the implementation is a monolith;
you can't mix and match different parts. And the distinctions
are blurred; most systems today will generate code at link time,
given certain options, and there is a definition interaction
between the library and the language in certain cases, such as
std::type_info. In the past, C compilers regularly "knew" the
semantics of certain standard functions (and generated them
inline), and it's to be expected that in the future, C++
compilers will know the details things like std::vector.

The standard is very clear about this. There's really no room
for discussion."

A very good reason to get away from the std libraries and "lock you in"
implementations. (That new fangled language is looking better all the
time!).

John
Jun 13 '07 #33

P: n/a
On 13 Jun, 11:31, "JohnQ" <johnqREMOVETHISprogram...@yahoo.comwrote:
Yes I may, and I do. Honestly, I'm hardly worried about being
standard-compliant. Indeed, that's like being put in a straitjacket.
That is of course entirely up to you. But if that's your approach, why
are you posting in a newsgroup whose purpose is deliberately and
explicitly restricted to only standard-compliant C++, the complete
opposite of what you are concerned with?

You aren't surprised by everyone else here being extremely concerned
with standard-compliance are you?

Gavin Deane

Jun 13 '07 #34

P: n/a

"Gavin Deane" <de*********@hotmail.comwrote in message
news:11**********************@x35g2000prf.googlegr oups.com...
On 13 Jun, 11:31, "JohnQ" <johnqREMOVETHISprogram...@yahoo.comwrote:
>Yes I may, and I do. Honestly, I'm hardly worried about being
standard-compliant. Indeed, that's like being put in a straitjacket.

That is of course entirely up to you. But if that's your approach, why
are you posting in a newsgroup whose purpose is deliberately and
explicitly restricted to only standard-compliant C++, the complete
opposite of what you are concerned with?

You aren't surprised by everyone else here being extremely concerned
with standard-compliance are you?
Don't be an extremist.

John
Jun 14 '07 #35

P: n/a
On Jun 10, 9:17 am, Pat <n...@none.nonewrote:
James Kanze <james.ka...@gmail.comwrote innews:11**********************@p77g2000hsh.google groups.com:
void Dog::GetName(std::string *s)
{
*s = "Dog";
}
Not related to your problem, but is there any reason for passing
a poniter to a string, and not simply returning a string.

Yes, passing a pointer is more efficient because it avoids copying the
entire object onto the stack. I try to always pass pointers or references,
unless the parameter is small (e.g. int). In this one simplified case it
might not make much difference, since the "=" operator is going to
basically perform a copy anyway. But for real world functions, it's a good
idea.
const char* Dog::GetName()
{
static const char* const s = "Dog";
return s;
};

how is this going to be expensive?Is it cost more than the size of a
pointer on stack?

regards,
FM.

Jun 14 '07 #36

P: n/a
terminator wrote:
[...about passing pointers to functions instead of values...]
>
const char* Dog::GetName()
{
static const char* const s = "Dog";
return s;
};

how is this going to be expensive?Is it cost more than the size of a
pointer on stack?
You don't need the static pointer:

const char* Dog::GetName()
{
return "Dog";
};

This works as well, since string literals live as long as the program runs.

And this is not expensive. The Foreposter talked about passing bigger
objects (like std::string), where copying is more expensive, so passing
them by reference makes sense:

void someFunction(const std::string& someString);

But for returning such objects, it is more expressive to return them
directly instead of passing a non-const reference or a pointer:

std::string someFunction();

--
Thomas
http://www.netmeister.org/news/learn2quote.html
Jun 14 '07 #37

This discussion thread is closed

Replies have been disabled for this discussion.