473,402 Members | 2,053 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,402 software developers and data experts.

C to C++ Syntax

Hello all,
I have a question regarding syntax, coming from a C background. In C,
if I had a function like this:

char *ParseDelimitedString(char *String,int DelimitedNumber,char
*Retval,int MaxBytes)
{
....
return(Retval);
}

This would be the way to return a string, instead of trying to return a
local variable. Of course, you can malloc() within the function and
return that, but I dont like having the caller know he has to free() it,
but I digress..
In C++, if I had this function as a static function, in some StringUtil
class:

std::string &StringUtil::ParseDelimitedString(string String,int
Num,string &Retval)
{
....
return(Retval);
}

or

std::string StringUtil::ParseDelimitedString(string String,int Num)
{
string LocalVar;

return(LocalVar);
}

From testing, I did see that returning the LocalVar created a 3rd
string (did not call the constructor), and did copy the data into the
string class. So, I assume this works, but about creating a new class,
for performance reasons is my question.

1) Which is correct? 1, 2, both?

2) Which would be faster? I assume #1 because it is just returning a
reference.

Thanks all.
Sep 28 '06 #1
8 2130
Brian C wrote:
I have a question regarding syntax, coming from a C background. In C,
if I had a function like this:

char *ParseDelimitedString(char *String,int DelimitedNumber,char
*Retval,int MaxBytes)
{
...
return(Retval);
Why parentheses?
}

This would be the way to return a string, instead of trying to return
a local variable. Of course, you can malloc() within the function and
return that, but I dont like having the caller know he has to free()
it, but I digress..
In C++, if I had this function as a static function, in some
StringUtil class:

std::string &StringUtil::ParseDelimitedString(string String,int
Num,string &Retval)
{
...
return(Retval);
That's OK. The user has to be notified that the third argument is
going to be used to return the string.

Passing a string to the function is better by a reference to const.
}

or

std::string StringUtil::ParseDelimitedString(string String,int Num)
{
string LocalVar;

return(LocalVar);
That's generally better. (plus the same sentiment about ref to const)
}

From testing, I did see that returning the LocalVar created a 3rd
string (did not call the constructor), and did copy the data into the
string class. So, I assume this works, but about creating a new class,
for performance reasons is my question.

1) Which is correct? 1, 2, both?
Both are "correct".
>
2) Which would be faster? I assume #1 because it is just returning a
reference.
Could be. Impossible to tell without the context and without actually
measuring.

What books are you reading? Try "Accelerated C++". Things like passing
by reference instead of by value should become second nature before you
can start talking performance.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 28 '06 #2
Victor Bazarov wrote:
Brian C wrote:
>I have a question regarding syntax, coming from a C background. In C,
if I had a function like this:

char *ParseDelimitedString(char *String,int DelimitedNumber,char
*Retval,int MaxBytes)
{
...
return(Retval);

Why parentheses?
Why not? I guess it's a habit of mine, I always do it.
>}

This would be the way to return a string, instead of trying to return
a local variable. Of course, you can malloc() within the function and
return that, but I dont like having the caller know he has to free()
it, but I digress..
In C++, if I had this function as a static function, in some
StringUtil class:

std::string &StringUtil::ParseDelimitedString(string String,int
Num,string &Retval)
{
...
return(Retval);

That's OK. The user has to be notified that the third argument is
going to be used to return the string.

Passing a string to the function is better by a reference to const.
>}

or

std::string StringUtil::ParseDelimitedString(string String,int Num)
{
string LocalVar;

return(LocalVar);

That's generally better. (plus the same sentiment about ref to const)
>}

From testing, I did see that returning the LocalVar created a 3rd
string (did not call the constructor), and did copy the data into the
string class. So, I assume this works, but about creating a new class,
for performance reasons is my question.

1) Which is correct? 1, 2, both?

Both are "correct".
>2) Which would be faster? I assume #1 because it is just returning a
reference.

Could be. Impossible to tell without the context and without actually
measuring.

What books are you reading? Try "Accelerated C++". Things like passing
by reference instead of by value should become second nature before you
can start talking performance.

V
I typically find books bad, except for reference because they don't
really show real-world examples. I've got a few C++ books. I've got one
from Deitel/Deitel (forget the name, it is at work), Practical C++ &
Teach Yourself C++ in 10 minutes (it lies, it isn't 10 minutes, good
reference book).

I will take a look at Accelerated C++, and also am going to look into
Effective C++. My personal experience with programming languages is that
you can read all you want, but until you actually code a real project in
them, you don't really learn. Guess it's me.
Sep 28 '06 #3
"Brian C" <br****@no.sp.a.m.dynamissoftware.comwrote in message
news:Xq*****************@news-wrt-01.rdc-nyc.rr.com...
Hello all,
I have a question regarding syntax, coming from a C background. In C, if I
had a function like this:

char *ParseDelimitedString(char *String,int DelimitedNumber,char
*Retval,int MaxBytes)
{
...
return(Retval);
}

This would be the way to return a string, instead of trying to return a
local variable. Of course, you can malloc() within the function and return
that, but I dont like having the caller know he has to free() it, but I
digress..
Of course you are just returning the same char pointer they passed in. The
user could just ignore the return value and use their passed in char
pointer, which is good.
In C++, if I had this function as a static function, in some StringUtil
class:

std::string &StringUtil::ParseDelimitedString(string String,int Num,string
&Retval)
{
...
return(Retval);
}
You are basically doing the exact same thing as with the C pointers except
using them as a reference. This would be my choice.
or

std::string StringUtil::ParseDelimitedString(string String,int Num)
{
string LocalVar;

return(LocalVar);
}

From testing, I did see that returning the LocalVar created a 3rd string
(did not call the constructor), and did copy the data into the string
class. So, I assume this works, but about creating a new class, for
performance reasons is my question.
This is making a local string and returning it on the stack. Yes, it has to
make a copy for this, and the calling function has to copy it off the stack
to use it. For extremely large strings, it may not even fit on the stack.
Although I do use this method myself for trivial strings (< 50 chars).
1) Which is correct? 1, 2, both?
Both are legal.
2) Which would be faster? I assume #1 because it is just returning a
reference.
Yes. #1 because it doesn't have to copy the contents of the string onto the
stack, nor copy it off again. But the user of the function has to know that
their passed in string will be modified, which they probably would anyway.
Thanks all.
You're welcome.
Sep 28 '06 #4
Jim Langston wrote:
"Brian C" <br****@no.sp.a.m.dynamissoftware.comwrote in message
news:Xq*****************@news-wrt-01.rdc-nyc.rr.com...
>Hello all,
I have a question regarding syntax, coming from a C background. In C, if I
had a function like this:

char *ParseDelimitedString(char *String,int DelimitedNumber,char
*Retval,int MaxBytes)
{
...
return(Retval);
}

This would be the way to return a string, instead of trying to return a
local variable. Of course, you can malloc() within the function and return
that, but I dont like having the caller know he has to free() it, but I
digress..

Of course you are just returning the same char pointer they passed in. The
user could just ignore the return value and use their passed in char
pointer, which is good.
>In C++, if I had this function as a static function, in some StringUtil
class:

std::string &StringUtil::ParseDelimitedString(string String,int Num,string
&Retval)
{
...
return(Retval);
}

You are basically doing the exact same thing as with the C pointers except
using them as a reference. This would be my choice.
>or

std::string StringUtil::ParseDelimitedString(string String,int Num)
{
string LocalVar;

return(LocalVar);
}

From testing, I did see that returning the LocalVar created a 3rd string
(did not call the constructor), and did copy the data into the string
class. So, I assume this works, but about creating a new class, for
performance reasons is my question.

This is making a local string and returning it on the stack. Yes, it has to
make a copy for this, and the calling function has to copy it off the stack
to use it. For extremely large strings, it may not even fit on the stack.
Although I do use this method myself for trivial strings (< 50 chars).
>1) Which is correct? 1, 2, both?

Both are legal.
>2) Which would be faster? I assume #1 because it is just returning a
reference.

Yes. #1 because it doesn't have to copy the contents of the string onto the
stack, nor copy it off again. But the user of the function has to know that
their passed in string will be modified, which they probably would anyway.
>Thanks all.

You're welcome.

Jim,
Thank you for your prompt and informative reply. I assumed both methods
would work, I was just wondering if there was a "preferred" C++ style to
doing so. I assume then it is just a matter of preference, and experience.
I usually look at performance as I have been coding since I had my
Commodore 64 (32KB of free RAM), and work on real-time trading systems
now, so I always bring that experience to my coding, even if not needed.
Sep 28 '06 #5
Brian C wrote:
[..]
I will take a look at Accelerated C++, and also am going to look into
Effective C++. My personal experience with programming languages is
that you can read all you want, but until you actually code a real
project in them, you don't really learn. Guess it's me.
No, it's not just you. It's generally true. Languages in general
(and not programming ones) require lots practice to get good.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 29 '06 #6
Victor Bazarov wrote:
Brian C wrote:
>[..]
I will take a look at Accelerated C++, and also am going to look into
Effective C++. My personal experience with programming languages is
that you can read all you want, but until you actually code a real
project in them, you don't really learn. Guess it's me.

No, it's not just you. It's generally true. Languages in general
(and not programming ones) require lots practice to get good.

V
I totally agree....and it really applies to things other than languages
.... I learned that after I gutted my bathroom =)
Sep 29 '06 #7
[snip]
>std::string StringUtil::ParseDelimitedString(string String,int Num)
{
string LocalVar;

return(LocalVar);
}

From testing, I did see that returning the LocalVar created a 3rd string
(did not call the constructor), and did copy the data into the string
class. So, I assume this works, but about creating a new class, for
performance reasons is my question.

This is making a local string and returning it on the stack. Yes, it has to
make a copy for this, and the calling function has to copy it off the stack
to use it. For extremely large strings, it may not even fit on the stack.
Although I do use this method myself for trivial strings (< 50 chars).
The amount of stack memory to allocate an std::string is always
sizeof(std::string). C++ does require every type to have a constant
size. The content of the string is stored somewhere else.

A lot of std::string implementations use a reference counted internal
structure so character-by-character copying is only done when you have
to change the string content. This makes the copying of string a cheap
operation. And because the local variable gets destroyed before the
return value can be accessed, deep copying can be totally eliminated.
>
>1) Which is correct? 1, 2, both?

Both are legal.
>2) Which would be faster? I assume #1 because it is just returning a
reference.
I would go for the second case because it is more readable. In the first
case the user can use either the return value or the last parameter to
access the result, and that is redundant (what if they are different?)
It is always good to make the interface as simple as possible.
>
Yes. #1 because it doesn't have to copy the contents of the string onto the
stack, nor copy it off again. But the user of the function has to know that
their passed in string will be modified, which they probably would anyway.
There are two optimizations in C++ that prevents a deep copy in #2.
First was described above. The second is called Named Return Value
optimization. Either of these optimizations will kick in.
>
>Thanks all.

You're welcome.

Regards,
Ben
Sep 29 '06 #8
"Brian C" <br****@no.sp.a.m.dynamissoftware.comwrote in message
news:o7***************@news-wrt-01.rdc-nyc.rr.com...
: [....] I assumed both methods
: would work, I was just wondering if there was a "preferred" C++ style
to
: doing so. I assume then it is just a matter of preference, and
experience.

If clean style is what you are looking for, you definitely should be
using the direct return syntax:
std::string ParseDelimitedString(std::string const& String, int Num);

Passing an extra parameter only to be used as storage has a name:
premature optimization

In the standard C++ library (the part that was added on top of C's lib),
the systematic approach is to always *return* output-only parameters
(even functions that output two values will return an std::pair).

Why is this better?
Returning the value allows the function to be used as part of a complex
expression. Passing an extra "storage object" parameter is just clutter.
Also, one thing you'll learn about C++ is that "const" is a good thing.
Experienced developers will write:
std::string const& paramA = ParseDelimitedString(commandLine,2);
std::string const& paramB = ParseDelimitedString(commandLine,2);
[NB: the use of a & is optional, although it used to help some compiler
to optimize-out an object copy. In this context, the reference
forces the lifetime of the returned temporary to be extended].

Now for the sad part:
There is an overhead in returning objects. Even though the compiler
is allowed to optimize-out object copies (search for RVO and
NRVO = [named] return value optimization), often the resulting code
will suffer unnecessary object duplications -- although most recent
compilers have become pretty good if all optimizations are enabled.

[[ Regarding benben's comment about strings being reference-counted:
Unfortunately, the most commonly used impementations of std::string
have given up on using reference-counting. They use other tricks
(like embedded storage of short strings, without mem allocation),
but reference counting is "out". ]]

In many cases you should not care about this overhead, but sometimes
it matters (e.g. a functions that returns a big collection of
generated data -- I then often use an output-only by-ref param).

This is recognized as a problem by the C++ standard committee.
In the next C++ standard, this is expected to be addressed by
a new "R-value reference" proposal allowing "moving constructors".

See: http://www.open-std.org/jtc1/sc22/wg...006/n1952.html
[If you are interested in the ongoing evolution of the C++ spec,
see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ ]

: I usually look at performance as I have been coding since I had my
: Commodore 64 (32KB of free RAM), and work on real-time trading systems
: now, so I always bring that experience to my coding, even if not
needed.
I also keep fond memories of assembly coding on the C64, and work
on embedded, image-processing, and real-time systems.
Yet I try to keep my code lean and clean when performance does not
matter, therefore my advice.

This said:
For parsing a delimited string, a true C++ style would be to either
provide an iterator-like interface, or a single function that
will parse the whole command line and return a vector<string>.
This will also improve performance because you won't re-parse
the whole containing string when accessing the 999's parameter.
I hope this helps,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form

Sep 29 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

699
by: mike420 | last post by:
I think everyone who used Python will agree that its syntax is the best thing going for it. It is very readable and easy for everyone to learn. But, Python does not a have very good macro...
22
by: Tuang | last post by:
I'm checking out Python as a candidate for replacing Perl as my "Swiss Army knife" tool. The longer I can remember the syntax for performing a task, the more likely I am to use it on the spot if...
14
by: Sandy Norton | last post by:
If we are going to be stuck with @decorators for 2.4, then how about using blocks and indentation to elminate repetition and increase readability: Example 1 --------- class Klass: def...
16
by: George Sakkis | last post by:
I'm sure there must have been a past thread about this topic but I don't know how to find it: How about extending the "for <X> in" syntax so that X can include default arguments ? This would be very...
23
by: Carter Smith | last post by:
http://www.icarusindie.com/Literature/ebooks/ Rather than advocating wasting money on expensive books for beginners, here's my collection of ebooks that have been made freely available on-line...
19
by: Nicolas Fleury | last post by:
Hi everyone, I would to know what do you think of this PEP. Any comment welcomed (even about English mistakes). PEP: XXX Title: Specialization Syntax Version: $Revision: 1.10 $...
4
by: Jeremy Yallop | last post by:
Looking over some code I came across a line like this if isalnum((unsigned char)c) { which was accepted by the compiler without complaint. Should the compiler have issued a diagnostic in this...
177
by: C# Learner | last post by:
Why is C syntax so uneasy on the eye? In its day, was it _really_ designed by snobby programmers to scare away potential "n00bs"? If so, and after 50+ years of programming research, why are...
4
by: Bob hotmail.com> | last post by:
Everyone I have been spending weeks looking on the web for a good tutorial on how to use regular expressions and other methods to satisfy my craving for learning how to do FAST c-style syntax...
3
by: Manuel | last post by:
I'm trying to compile glut 3.7.6 (dowbloaded from official site)using devc++. So I've imported the glut32.dsp into devc++, included manually some headers, and start to compile. It return a very...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.