473,387 Members | 1,476 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,387 software developers and data experts.

Strings and refs, need comments on code

Hi all,

I've been having questions about strings, references,
initializations... I've created code (which will not compile due to a
reference problem) and I'd like comments on why this won't work and any
other comment to the code with efficiency in mind.

#include <iostream>
#include <string>

using std::cout;
using std::string;

class myClass {
public:
myClass(string s) : str(s) { }
~myClass() { }

string& getStr() const { return str; }

private:
string str;
};

int main() {

string * s = new string("FOO");
myClass * m = new myClass(*s);

cout << m->getStr() << std::endl;

delete s;
delete m;

return 0;
}

Some questions:
1 - Should constructor receive a &? (would it be faster? now, it's
copying the string in str(s), right?)
2 - why returning string& is not working? (returning just string would
return a copy of str, right?)
3 - How can I return the string, as efficiently as possible but making
sure it cannot be modified?

Any other comments are welcome.

Thanks,

Paulo Matos

Jul 23 '05 #1
7 1518
pmatos wrote:
I've been having questions about strings, references,
initializations... I've created code (which will not compile due to a
reference problem) and I'd like comments on why this won't work and any
other comment to the code with efficiency in mind.

#include <iostream>
#include <string>

using std::cout;
using std::string;

class myClass {
public:
myClass(string s) : str(s) { }
Definitely should be

myClass(string const& s) : str(s) { }
~myClass() { }

string& getStr() const { return str; }
If your object is 'const', you can't return a non-const reference
to a member. It breaks the assumption that the object is const.

private:
string str;
};

int main() {

string * s = new string("FOO");
myClass * m = new myClass(*s);
You really shouldn't use dynamic memory unless you _have_to_. Just
plain

myClass m("FOO");

will work fine in this particular case.

cout << m->getStr() << std::endl;
If you use a local object, you'll have to change to m.getStr().

delete s;
delete m;
.... and there will be no need to delete anything.

return 0;
}

Some questions:
1 - Should constructor receive a &? (would it be faster? now, it's
copying the string in str(s), right?)
It should receive a reference, but it should still copy it locally.
As originally posted, two strings are created instead of one.
2 - why returning string& is not working? (returning just string would
return a copy of str, right?)
Right. Just return a 'string const&'.
3 - How can I return the string, as efficiently as possible but making
sure it cannot be modified?


Return by a reference to const.

V
Jul 23 '05 #2
pmatos wrote:
Hi all,

I've been having questions about strings, references,
initializations... I've created code (which will not compile due to a
reference problem) and I'd like comments on why this won't work and any
other comment to the code with efficiency in mind.
I believe that strings generally have efficient implementations. It
does depend on your library, but they should normally have copy-on-write
reference counting, or something of that sort. I'm sure someone will
correct me if I'm wrong, but I believe that it is reasonable to pass
strings around with as little care about efficiency as if you were
passing ints or chars.
#include <iostream>
#include <string>

using std::cout;
using std::string;

class myClass {
public:
myClass(string s) : str(s) { }
~myClass() { }

string& getStr() const { return str; }

private:
string str;
};

int main() {

string * s = new string("FOO");
myClass * m = new myClass(*s);

cout << m->getStr() << std::endl;

delete s;
delete m;

return 0;
}

Some questions:
1 - Should constructor receive a &? (would it be faster? now, it's
copying the string in str(s), right?)
See above for strings. But more generally, yes, if you are passing
something like a large struct or a container you can pass it as a const
T& (const is important) and get improved efficiency.
2 - why returning string& is not working? (returning just string would
return a copy of str, right?)
Give us a clue, what is the error message?
3 - How can I return the string, as efficiently as possible but making
sure it cannot be modified?


See above for strings. But more generally, yes, this is something you
might need to worry about for large types, and it is a bit more painful
than passing parameters because you have to worry more about the
lifetime of the objects. In my code I often use "out parameters", i.e.
I require that the caller declares an (empty) variable for the result
and pass it as a reference parameter. Other options include smart
pointers. I believe that you will find some useful material in the FAQ.

--Phil.
Jul 23 '05 #3
Victor Bazarov <v.********@comAcast.net> wrote in news:BJCpe.81519
$N********@newsread1.mlpsca01.us.to.verio.net:
pmatos wrote:
I've been having questions about strings, references,
initializations... I've created code (which will not compile due to a
reference problem) and I'd like comments on why this won't work and any
other comment to the code with efficiency in mind.

#include <iostream>
#include <string>

using std::cout;
using std::string;

class myClass {
public:
myClass(string s) : str(s) { }


Definitely should be

myClass(string const& s) : str(s) { }
~myClass() { }

string& getStr() const { return str; }


If your object is 'const', you can't return a non-const reference
to a member. It breaks the assumption that the object is const.

private:
string str;
};

int main() {

string * s = new string("FOO");
myClass * m = new myClass(*s);


You really shouldn't use dynamic memory unless you _have_to_. Just
plain

myClass m("FOO");

will work fine in this particular case.

cout << m->getStr() << std::endl;


If you use a local object, you'll have to change to m.getStr().

delete s;
delete m;


... and there will be no need to delete anything.


You forgot to mention... and no need to delete anything in a particular
order. (OK, 'need' may be a little strong, but we'll stick with it for
now). As it is now, *m is holding a reference to *s. Between "delete s;"
and "delete m;", m is a timebomb waiting to go off. It now has a reference
to an invalid object. In a more complex program where these two delete
statements aren't next to each other, one may be tempted to try using the
*m object to access the string it references......

return 0;
}

Some questions:
1 - Should constructor receive a &? (would it be faster? now, it's
copying the string in str(s), right?)


It should receive a reference, but it should still copy it locally.
As originally posted, two strings are created instead of one.
2 - why returning string& is not working? (returning just string would
return a copy of str, right?)


Right. Just return a 'string const&'.
3 - How can I return the string, as efficiently as possible but making
sure it cannot be modified?


Return by a reference to const.

V


Jul 23 '05 #4
Andre Kostur wrote:
Victor Bazarov <v.********@comAcast.net> wrote in news:BJCpe.81519
$N********@newsread1.mlpsca01.us.to.verio.net:

pmatos wrote:
I've been having questions about strings, references,
initializations... I've created code (which will not compile due to a
reference problem) and I'd like comments on why this won't work and any
other comment to the code with efficiency in mind.

#include <iostream>
#include <string>

using std::cout;
using std::string;

class myClass {
public:
myClass(string s) : str(s) { }
Definitely should be

myClass(string const& s) : str(s) { }

~myClass() { }

string& getStr() const { return str; }


If your object is 'const', you can't return a non-const reference
to a member. It breaks the assumption that the object is const.

private:
string str;
};

int main() {

string * s = new string("FOO");
myClass * m = new myClass(*s);


You really shouldn't use dynamic memory unless you _have_to_. Just
plain

myClass m("FOO");

will work fine in this particular case.

cout << m->getStr() << std::endl;


If you use a local object, you'll have to change to m.getStr().

delete s;
delete m;


... and there will be no need to delete anything.

You forgot to mention... and no need to delete anything in a particular
order. (OK, 'need' may be a little strong, but we'll stick with it for
now). As it is now, *m is holding a reference to *s.


Huh? '*m' is an object of class myClass, which happens to have 'str' as
its only data member, and it's not a reference...
Between "delete s;"
and "delete m;", m is a timebomb waiting to go off. It now has a reference
to an invalid object. In a more complex program where these two delete
statements aren't next to each other, one may be tempted to try using the
*m object to access the string it references......
You need to look at the original post again, I believe.

return 0;
}


V
Jul 23 '05 #5
Phil Endecott wrote:
pmatos wrote:
Hi all,

I've been having questions about strings, references,
initializations... I've created code (which will not compile due to a
reference problem) and I'd like comments on why this won't work and any
other comment to the code with efficiency in mind.


I believe that strings generally have efficient implementations. It
does depend on your library, but they should normally have copy-on-write
reference counting, or something of that sort. I'm sure someone will
correct me if I'm wrong, but I believe that it is reasonable to pass
strings around with as little care about efficiency as if you were
passing ints or chars.


That may be true, but why take the chance that it isn't? See below.
#include <iostream>
#include <string>

using std::cout;
using std::string;

class myClass {
public:
myClass(string s) : str(s) { }
~myClass() { }

string& getStr() const { return str; }

private:
string str;
};

int main() {

string * s = new string("FOO");
myClass * m = new myClass(*s);

cout << m->getStr() << std::endl;

delete s;
delete m;

return 0;
}

Some questions:
1 - Should constructor receive a &? (would it be faster? now, it's
copying the string in str(s), right?)


See above for strings. But more generally, yes, if you are passing
something like a large struct or a container you can pass it as a const
T& (const is important) and get improved efficiency.


I don't think you should make an exception for std::string. The whole
point of abstraction is so you don't have to know whether or not the
class' implementation is "fast enough." Be consistent, and pass
references (to const if possible) whenever you're dealing with
*anything* other than a primitive type.
2 - why returning string& is not working? (returning just string would
return a copy of str, right?)


Give us a clue, what is the error message?


He has a const function returning a non-const reference to internal
data. That isn't allowed.
3 - How can I return the string, as efficiently as possible but making
sure it cannot be modified?


See above for strings. But more generally, yes, this is something you
might need to worry about for large types, and it is a bit more painful
than passing parameters because you have to worry more about the
lifetime of the objects. In my code I often use "out parameters", i.e.
I require that the caller declares an (empty) variable for the result
and pass it as a reference parameter. Other options include smart
pointers. I believe that you will find some useful material in the FAQ.


I think Victor's response to this was much simpler: return a reference
to const.

Kristo

Jul 23 '05 #6
pmatos wrote:
string * s = new string("FOO");
myClass * m = new myClass(*s);
Don't use 'new' without a major reason. "I need an object inside this
function" is no reason. Just construct the object directly:

string s = "FOO";
1 - Should constructor receive a &? (would it be faster? now, it's
copying the string in str(s), right?)


When starting a project, never worry about program speed. Do worry about
programmer speed. Programmers should always use the similar constructions at
similar places, just to preserve legibility. If everything else used 'const
&' and this one did not, that should raise an unanswerable question, why is
this different?

Use 'const &' because big objects need that to be fast.

--
Phlip
http://www.c2.com/cgi/wiki?ZeekLand

Jul 23 '05 #7
Victor Bazarov <v.********@comAcast.net> wrote in
news:px*******************@newsread1.mlpsca01.us.t o.verio.net:
Andre Kostur wrote:
Victor Bazarov <v.********@comAcast.net> wrote in news:BJCpe.81519
$N********@newsread1.mlpsca01.us.to.verio.net:

pmatos wrote:

I've been having questions about strings, references,
initializations... I've created code (which will not compile due to
a reference problem) and I'd like comments on why this won't work
and any other comment to the code with efficiency in mind.

#include <iostream>
#include <string>

using std::cout;
using std::string;

class myClass {
public:
myClass(string s) : str(s) { }

Definitely should be

myClass(string const& s) : str(s) { }
~myClass() { }

string& getStr() const { return str; }

If your object is 'const', you can't return a non-const reference
to a member. It breaks the assumption that the object is const.
private:
string str;
};

int main() {

string * s = new string("FOO");
myClass * m = new myClass(*s);

You really shouldn't use dynamic memory unless you _have_to_. Just
plain

myClass m("FOO");

will work fine in this particular case.
cout << m->getStr() << std::endl;

If you use a local object, you'll have to change to m.getStr().
delete s;
delete m;

... and there will be no need to delete anything.

You forgot to mention... and no need to delete anything in a
particular order. (OK, 'need' may be a little strong, but we'll
stick with it for now). As it is now, *m is holding a reference to
*s.


Huh? '*m' is an object of class myClass, which happens to have 'str'
as its only data member, and it's not a reference...


Ooops.... my bad. Somehow I figured the private member was a string&.
Completely my error. Must clean my eyeballs.

I agree with your original points.... why bother to dynamically allocate
when you're (the OP) treating it as a local variable anyway.


Jul 23 '05 #8

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

Similar topics

0
by: Ali | last post by:
I am in great need of code that will make a dome. I would like the inputs to be similar to that of the sphere. ie: pos=(x0, y0, z0) radius = R color = (r,g,b) etc. I am using VPython of...
1
by: Cibulya Dmitriy | last post by:
Hi All, I want to catch the next MSSQL error in my SQL code with following continue calculations Server: Msg 17, Level 16, State 1, Line 1 SQL Server does not exist or access denied.
34
by: Mark Kamoski | last post by:
Hi-- Please help. I need a code sample for bubble sort. Thank you. --Mark
2
by: Mark Kamoski | last post by:
Hi Everyone-- Please help. I need a code sample for merge sort. Thank you. --Mark
1
by: Riyadh Hossain | last post by:
I am developing USPS shipping API for my site. All the work is going on testing phase. My site uses PHP/MySQL. Now I am working on USPS tracking/confirm. I can send request and get responses from...
0
by: ravibrl | last post by:
Hey I need c++ code to access a webpage and download some software. If I execute that it should download that software and it should install it in my system. Give suggestions how to write that code...
3
by: dee vee bee | last post by:
this is my project i need a code that will show like this.. "first number __" "second number ___" "choose operation: addition..subtraction..multiplication..division" "the answer is ___" the...
1
by: saravanatmm | last post by:
I need javascript code for validate the email address. Email address field cannot allowed the capital letters, special characters except '@' symbol. But can allowed the small letters, numeric...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
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...

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.