From: Ulrich Eckhardt on
Gerry Hickman wrote:
> Doug Harrison offered this example:
>
> ----- example start -----
>
> I would use pass-by-reference to avoid this needless cost, e.g.
>
> vector<string>::size_type
> void GetDeviceClasses(vector<string>& guids)
> {
[...]
> returns guids.size();
> }

Funny. Talking about needless costs and then returning redundant data - the
size can be retrieved from the vector. Anyway, why would you write anything
but clear code unless you first determined that it's a bottleneck? Just
return the vector by value.

> but when I came to actually code this, I ran into some problems.

This doesn't help. What problems?

> void PopulateStrings(vector<string> * guids)
> {
> guids->clear();
> guids->push_back("test1");
> guids->push_back("test2");
> }

While this code will work, there is one thing I object to: in C++, where you
have references, a pointer[1] means to me that something is optional, i.e.
passing zero is okay, but you don't mean that. Still, you must handle that
case, so either you just return (making it a non-error), throw an exception
(making it a runtime error) or use assert() (making it a programmer's
error).

Not checking it is bad practice and will get you larted if you happen to be
on my team.

Uli

[1] The exception is when an array/string is passed.

From: Gerry Hickman on
Hi,

Thanks to everyone who replied, I think I was confusing C with C++ style
earlier. I found this article:

<http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm>

that appears to explain both cases.

Charles Wang[MSFT] wrote:
> Hi Gerry,
> Could you please let us know what the problems you ran into if you used
> Doug's suggestion?
>
> It should also work if you use reference as following:
> ===================================
> vector<string> guids;
> PopulateStrings(guids);
> cout << "Count of guids is now " << guids.size(); // prints 2
>
> void PopulateStrings(vector<string> & guids)
> {
> guids.clear();
> guids.push_back("test1");
> guids.push_back("test2");
> }
> ==================================
>
> Best regards,
> Charles Wang
> Microsoft Online Community Support
> =====================================================
> When responding to posts, please "Reply to Group" via
> your newsreader so that others may learn and benefit
> from this issue.
> ======================================================
> This posting is provided "AS IS" with no warranties, and confers no rights.
> ======================================================
>
>
>


--
Gerry Hickman (London UK)
From: Doug Harrison [MVP] on
On Fri, 10 Aug 2007 08:59:05 +0200, Ulrich Eckhardt
<eckhardt(a)satorlaser.com> wrote:

>Gerry Hickman wrote:
>> Doug Harrison offered this example:
>>
>> ----- example start -----
>>
>> I would use pass-by-reference to avoid this needless cost, e.g.
>>
>> vector<string>::size_type
>> void GetDeviceClasses(vector<string>& guids)
>> {
>[...]
>> returns guids.size();
>> }
>
>Funny. Talking about needless costs and then returning redundant data - the
>size can be retrieved from the vector.

What's "funny" is to compare returning a vector<string> by value to
returning its size, the latter being as close to a free operation as there
is, both in terms of complexity and exception safety. Not to mention,
returning the size is a useful thing to do.

>Anyway, why would you write anything
>but clear code unless you first determined that it's a bottleneck? Just
>return the vector by value.

I don't know what's "funnier"; suggesting the code I presented isn't
"clear", recommending returning a vector<string> by value, or equating
returning a vector<string> by value with returning size(). You could almost
take it on the road, I think. :)

--
Doug Harrison
Visual C++ MVP
From: Bo Persson on
Doug Harrison [MVP] wrote:
:: On Fri, 10 Aug 2007 08:59:05 +0200, Ulrich Eckhardt
:: <eckhardt(a)satorlaser.com> wrote:
::
::: Gerry Hickman wrote:
:::: Doug Harrison offered this example:
::::
:::: ----- example start -----
::::
:::: I would use pass-by-reference to avoid this needless cost, e.g.
::::
:::: vector<string>::size_type
:::: void GetDeviceClasses(vector<string>& guids)
:::: {
::: [...]
:::: returns guids.size();
:::: }
:::
::: Funny. Talking about needless costs and then returning redundant
::: data - the size can be retrieved from the vector.
::
:: What's "funny" is to compare returning a vector<string> by value to
:: returning its size, the latter being as close to a free operation
:: as there is, both in terms of complexity and exception safety. Not
:: to mention, returning the size is a useful thing to do.

How do you know that it is useful? Always?

Assuming that we are trying to optimize a time-critical piece of code,
why return a value that isn't asked for? Especially as it is also
returned as a part of the guids parameter.


It is also often not considered good style to have both a return value
and out-parameters. If you need to, you can have several
out-parameters, and not single out one of them as a return value.


Bo Persson


From: Doug Harrison [MVP] on
On Fri, 10 Aug 2007 22:47:34 +0200, "Bo Persson" <bop(a)gmb.dk> wrote:

>Doug Harrison [MVP] wrote:
>:: On Fri, 10 Aug 2007 08:59:05 +0200, Ulrich Eckhardt
>:: <eckhardt(a)satorlaser.com> wrote:
>::
>::: Gerry Hickman wrote:
>:::: Doug Harrison offered this example:
>::::
>:::: ----- example start -----
>::::
>:::: I would use pass-by-reference to avoid this needless cost, e.g.
>::::
>:::: vector<string>::size_type
>:::: void GetDeviceClasses(vector<string>& guids)
>:::: {
>::: [...]
>:::: returns guids.size();
>:::: }
>:::
>::: Funny. Talking about needless costs and then returning redundant
>::: data - the size can be retrieved from the vector.
>::
>:: What's "funny" is to compare returning a vector<string> by value to
>:: returning its size, the latter being as close to a free operation
>:: as there is, both in terms of complexity and exception safety. Not
>:: to mention, returning the size is a useful thing to do.
>
>How do you know that it is useful? Always?

Often, after using a function with a name such as "GetDeviceClasses", a
programmer wants to know how many such classes were found; he may be
interested in the exact number, or he may just treat it as a boolean.
Provided one can indicate errors in some other way, there's no reason not
to return the number of items that were found, elements read, etc.

>Assuming that we are trying to optimize a time-critical piece of code,
>why return a value that isn't asked for? Especially as it is also
>returned as a part of the guids parameter.

The code in question populates a vector<string>, and judging by its name,
probably enumerates the registry. I don't understand how anyone could worry
about the efficiency of returning vector::size() in this context.

(Granted, if you were talking about std::list, you might have a very, very
tiny point, but to date, I'm unaware of anyone making vector::size worse
than O(1).)

>It is also often not considered good style to have both a return value
>and out-parameters.

This is not an example of bad style.

(Q: What do you think this interface is equivalent to, if anything? To help
you focus, you can limit yourself to standard functions.)

>If you need to, you can have several
>out-parameters, and not single out one of them as a return value.

Yes, you can do that if you need to.

--
Doug Harrison
Visual C++ MVP