473,763 Members | 5,396 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Returning by value (here we go again!)


AnyClass Blah()
{
AnyClass poo;

return poo;
}
As we all know, in the above, the compiler is entitled to:

1) Create the object "poo"
2) Create a copy of "poo"
3) Destroy "poo"
4) Return the copy

or

1) Create the object "poo"
2) Return "poo"
On account of the first choice, whether a copy is made or not, the copy
constructor must be public.

First of all, I think it would be handy if we had a new type of "return"
statement in C++, one which makes it so that the actual object is returned
(no copy made) and as such the copy constructor wouldn't need to be
public... allowing the likes of the following:

std::ostream Blah()
{
std::ostream poo;

return_actual_o bject poo;
}
Anyway...

To achieve this, at the moment I'm using auto_ptr, as follows:

auto_ptr<AnyCla ss> Blah()
{
auto_ptr<AnyCla ss> poo( new AnyClass );

return poo;
}

int main()
{
auto_ptr<AnyCla ss> const &milk = Blah();

//now work with it as I please!
//and if I want reference syntax:

AnyClass const& cheese = *milk;

cheese.MemberFu nction();
}
The compiler still has the choice of copying the auto_ptr... but it's a hell
of a lot better than copying the entire object! Plus, I can return an
"std::ostre am" by value... (kind of!).

AAnnyywwaayy... looking through a C++ reference today I was sort of shocked
to see:

basic_string::s ubstr
basic_string substr(size_typ e off = 0,
size_type count = npos) const;
The member function returns an object whose controlled sequence is a copy of
up to count elements of the controlled sequence beginning at position off.
It returns by value! AAAAAAaaahhhhhh hh! throw Inefficiency(); !
-JKop

Jul 22 '05 #1
11 1942
JKop wrote:


First of all, I think it would be handy if we had a new type of "return"
statement in C++, one which makes it so that the actual object is returned
(no copy made) and as such the copy constructor wouldn't need to be
public... allowing the likes of the following:

std::ostream Blah()
{
std::ostream poo;

return_actual_o bject poo;
}
The problem with this is not the return.
The problem is that copying a stream object is forbidden.

As for your suggestion.
Now we have a simple rule: Every local object gets destroyed at the
end of the function. Your suggestion would make an exception to that.
What would be scope of that local object? In other words: when
does it get destroyed?

Anyway...

To achieve this, at the moment I'm using auto_ptr, as follows:

auto_ptr<AnyCla ss> Blah()
{
auto_ptr<AnyCla ss> poo( new AnyClass );

return poo;
}
Fine. In other words: You dynamically allocate the object
and ask the caller to free it. Fine. In order to help
the caller somewhat, you put an envelope around it. Also
fine.

[snip]
The compiler still has the choice of copying the auto_ptr... but it's a hell
of a lot better than copying the entire object! Plus, I can return an
"std::ostre am" by value... (kind of!).

AAnnyywwaayy... looking through a C++ reference today I was sort of shocked
to see:

basic_string::s ubstr
basic_string substr(size_typ e off = 0,
size_type count = npos) const;
The member function returns an object whose controlled sequence is a copy of
up to count elements of the controlled sequence beginning at position off.

It returns by value! AAAAAAaaahhhhhh hh! throw Inefficiency(); !


You should not be shocked.

string a = "abcd";
string b = a.substr(2) + "xyz";

In order for this to work, there is no other choice as to return a copy.
Return value optimization takes care of the rest.

--
Karl Heinz Buchegger
kb******@gascad .at
Jul 22 '05 #2
In article <Ar************ *******@news.in digo.ie>,
JKop <NU**@NULL.NULL > wrote:
First of all, I think it would be handy if we had a new type of "return"
statement in C++, one which makes it so that the actual object is returned
(no copy made) and as such the copy constructor wouldn't need to be
public... allowing the likes of the following:

std::ostream Blah()
{
std::ostream poo;

return_actual_o bject poo;
}
I agree, at least partly. This can be achieved with move semantics:

http://www.open-std.org/jtc1/sc22/wg...004/n1690.html
http://www.open-std.org/jtc1/sc22/wg...2002/n1377.htm

which unfortunately is not part of C++ today. If you would like to see
move semantics become part of C++, make sure your national
representative on the C++ committee knows that.

Movable, but non-copyable types with non-cv qualified auto storage
should be returnable by value from functions. For example see:

http://www.open-std.org/jtc1/sc22/wg...77.htm#Moving%
20from%20local% 20values

std::streams could be made movable, and remain non-copyable.
Anyway...

To achieve this, at the moment I'm using auto_ptr, as follows:

auto_ptr<AnyCla ss> Blah()
{
auto_ptr<AnyCla ss> poo( new AnyClass );

return poo;
}

int main()
{
auto_ptr<AnyCla ss> const &milk = Blah();

//now work with it as I please!
//and if I want reference syntax:

AnyClass const& cheese = *milk;

cheese.MemberFu nction();
}
<nod> Today's workarounds are ugly.
AAnnyywwaayy... looking through a C++ reference today I was sort of shocked
to see:

basic_string::s ubstr
basic_string substr(size_typ e off = 0,
size_type count = npos) const;
The member function returns an object whose controlled sequence is a copy of
up to count elements of the controlled sequence beginning at position off.

It returns by value! AAAAAAaaahhhhhh hh! throw Inefficiency(); !


A good compiler can optimize away this copy if the client is using
substr to construct another string. But if it is using substr to assign
into an existing string a temporary is still created.

It would be a lot more palatable with move semantics. The temporary
could still be created, but then it would be moved from, instead of
copied from.

-Howard
Jul 22 '05 #3

"JKop" <NU**@NULL.NULL > wrote in message
news:Ar******** ***********@new s.indigo.ie...

AnyClass Blah()
{
AnyClass poo;

return poo;
}
As we all know, in the above, the compiler is entitled to:

1) Create the object "poo"
2) Create a copy of "poo"
3) Destroy "poo"
4) Return the copy

or

1) Create the object "poo"
2) Return "poo"

or optimize away the function call to Blah and create the AnyClass object at
the point of the function call instead. However, whether this can be done
and makes sense depends on the context.

On account of the first choice, whether a copy is made or not, the copy
constructor must be public.
Well, what´s the problem with that. Declaring the copy ctor
private/protected is an idiom that signals that no copy can be created.

First of all, I think it would be handy if we had a new type of "return"
statement in C++, one which makes it so that the actual object is returned
(no copy made) and as such the copy constructor wouldn't need to be
public... allowing the likes of the following:

std::ostream Blah()
{
std::ostream poo;

return_actual_o bject poo;
}

As Karl Heinz already mentioned there is the issue of scope and automatic
destruction, which makes absolutely sense. Otherwise we´re going into the
C#, Java etc. direction where garbage control ist needed. The pros & cons of
GC are a topic themselves.

Anyway...

To achieve this, at the moment I'm using auto_ptr, as follows:

auto_ptr<AnyCla ss> Blah()
{
auto_ptr<AnyCla ss> poo( new AnyClass );

return poo;
}

int main()
{
auto_ptr<AnyCla ss> const &milk = Blah();

//now work with it as I please!
//and if I want reference syntax:

AnyClass const& cheese = *milk;

cheese.MemberFu nction();
}

So you´re using a pointer with transferable ownership but you´re heading in
the direction where you clutter your code with mostly unnecessary
constructions like that. With a proper design such things should rarely be
required.

The compiler still has the choice of copying the auto_ptr... but it's a hell of a lot better than copying the entire object! Plus, I can return an
"std::ostre am" by value... (kind of!).
BTW, copying streams is not allowed.

AAnnyywwaayy... looking through a C++ reference today I was sort of shocked to see:

basic_string::s ubstr
basic_string substr(size_typ e off = 0,
size_type count = npos) const;
The member function returns an object whose controlled sequence is a copy of up to count elements of the controlled sequence beginning at position off.
It returns by value! AAAAAAaaahhhhhh hh! throw Inefficiency(); !


Hold you breath ;-) Returning by value instead of reference makes absolutely
sense in this case, as already pointed out by Karl Heinz. However, I´d
suggest that you read the respective chapter 23 in Scott Meyers "Effective
C++".

As he says: [quote] "It all boils down to this: when deciding between
returning a reference and returning an object, your job is to make the
choice that does the right thing. Let your compiler vendors wrestle with
figuring out how to make that choice as inexpensive as possible" [quote]

Chris
Jul 22 '05 #4
JKop wrote:
AnyClass Blah(void) {
AnyClass poo;
return poo;
}
As we all know, in the above, the compiler is entitled to:

1) Create the object "poo"
2) Create a copy of "poo"
3) Destroy "poo"
4) Return the copy

or

1) Create the object "poo"
2) Return "poo"
On account of the first choice, whether a copy is made or not,
the copy constructor must be public.

First of all, I think it would be handy if we had a new type of "return"
statement in C++, one which makes it so that the actual object is returned
(no copy made) and as such the copy constructor wouldn't need to be
public... allowing the likes of the following:

std::ostream Blah()
{
std::ostream poo;

return_actual_o bject poo;
}
Anyway...

To achieve this, at the moment I'm using auto_ptr, as follows:

auto_ptr<AnyCla ss> Blah()
{
auto_ptr<AnyCla ss> poo( new AnyClass );

return poo;
}

int main()
{
auto_ptr<AnyCla ss> const &milk = Blah();

//now work with it as I please!
//and if I want reference syntax:

AnyClass const& cheese = *milk;

cheese.MemberFu nction();
}
The compiler still has the choice of copying the auto_ptr... but it's a hell
of a lot better than copying the entire object! Plus, I can return an
"std::ostre am" by value... (kind of!).

AAnnyywwaayy... looking through a C++ reference today I was sort of shocked
to see:

basic_string::s ubstr
basic_string substr(size_typ e off = 0,
size_type count = npos) const;
The member function returns an object whose controlled sequence is a copy of
up to count elements of the controlled sequence beginning at position off.
It returns by value! AAAAAAaaahhhhhh hh! throw Inefficiency(); !
You are confused.
cat main.cc #include <iostream>

class AnyClass {
private:
// representation
int I;
public:
// operators
friend
std::ostream& operator<<(std: :ostream& os, const AnyClass& a);
// constructors
AnyClass(int i = 0): I(i) {
std::cout << "AnyClass::AnyC lass(int)" << std::endl;
}
AnyClass(const AnyClass& a): I(a.I) {
std::cout << "AnyClass::AnyC lass(const AnyClass&)"
<< std::endl;
}
~AnyClass(void) {
std::cout << "AnyClass::~Any Class(void)" << std::endl;
}
};

inline
std::ostream& operator<<(std: :ostream& os, const AnyClass& a) {
return os << a.I;
}

AnyClass Blah(void) {
AnyClass poo;
return poo;
}

int main(int argc, char* argv[]) {
AnyClass a = Blah();
std::cout << "a = " << a << std::endl;
return 0;
}
g++ -Wall -ansi -pedantic -o main main.cc
./main

AnyClass::AnyCl ass(int)
a = 0
AnyClass::~AnyC lass(void)

1. ) The copy constructor is *never* called,
2. ) AnyClass(int) initializes the return value directly and
3. ) Blah(void) initializes object a directly.

You can't write code that is more efficient than that.
Jul 22 '05 #5
1. ) The copy constructor is *never* called,
With your particular compiler, yes.
2. ) AnyClass(int) initializes the return value directly and
With your particular compiler, yes.
3. ) Blah(void) initializes object a directly.
With your particular compiler, yes.
You can't write code that is more efficient than that.


With your particular compiler, yes.
What I'm getting at is that when you return an object by value, under the
duress of the Standard, the compiler is entitled to make copies and destroy
originals.
-JKop
Jul 22 '05 #6

"JKop" <NU**@NULL.NULL > schrieb im Newsbeitrag
news:Hs******** ***********@new s.indigo.ie...
1. ) The copy constructor is *never* called,
With your particular compiler, yes.
2. ) AnyClass(int) initializes the return value directly and


With your particular compiler, yes.
3. ) Blah(void) initializes object a directly.


With your particular compiler, yes.
You can't write code that is more efficient than that.


With your particular compiler, yes.
What I'm getting at is that when you return an object by value, under the
duress of the Standard, the compiler is entitled to make copies and

destroy originals.


Of course it is and it makes good sense. If you return by value you actually
ask the compiler to create a copy - well, if it can avoid it the better. The
destruction of the original has nothing to do by return the object by value
but rather by reaching the end of scope.
Furthermore there are many cases where this behavior is absolutely desirable
as it's been pointed out for example by Karl Heinz. Check out Scott Meyers'
Effective C++ item 23.

Chris
Jul 22 '05 #7
JKop wrote:
1. ) The copy constructor is *never* called,


With your particular compiler, yes.
2. ) AnyClass(int) initializes the return value directly and


With your particular compiler, yes.
3. ) Blah(void) initializes object a directly.


With your particular compiler, yes.
You can't write code that is more efficient than that.


With your particular compiler, yes.

What I'm getting at is that when you return an object by value,
under the duress of the Standard,
the compiler is entitled to make copies and destroy originals.


Correct.
The C++ standard specifies the language and not the implementation.
The quality of the implementation is governed by the marketplace.
You are expect, as a responsible consumer,
to shop for a compiler that performs as required.
There are probably quality C++ compilers for virtually every platform
that might be a target for the code that you are writing.
Jul 22 '05 #8
JKop wrote:
AnyClass Blah()
{
AnyClass poo;

return poo;
}

As we all know, in the above, the compiler is entitled to:

1) Create the object "poo"
2) Create a copy of "poo"
3) Destroy "poo"
4) Return the copy

or

1) Create the object "poo"
2) Return "poo"
You're not actually looking at what happens at the end of Blah, you're
looking at the boundary between Blah and its caller. The second method
only happens when the compiler is able to merge part of the caller with
Blah, ie the second case doesn't skip creating the copy, it skips
creating poo.

As for actual implementation, this would have to happen before Blah
returned, because if poo is to be copied it still needs to exist. But
using the copy constructor works in the general case, whereas skipping
it will only work if you only call Blah in specific ways. That is, how
Blah can be optimized depends on the code that calls Blah rather than
Blah's code itself.

In particular:
AnyClass tar;
try
{
tar = Blah();
}
catch (...)
{
}
will not work if the copy is skipped. If poo's constructor throws and
it's "returning the actual object", tar is left in an inconsistent state.

As opposed to:
AnyClass tar = Blah();
where tar cannot be constructed at all if the constructor throws poo.

I think that a new type of return that always returned the object rather
than copying would have some very complicated consequences.

I suppose if you were really desperate, you could simulate how a
theoretical compiler might do it with something like:

AnyClass &Blah(void *carrots)
{
AnyClass *poo = new(carrots) AnyClass;

return *poo;
}

void Cactus(void)
{
char cement[sizeof AnyClass];
AnyClass &tar = Blah(cement);

tar.MemberFunct ion();

tar.~AnyClass() ;
}

hm... probably. Except you'd want some sort of template to automate
that mess.
AAnnyywwaayy... looking through a C++ reference today I was sort of shocked
to see:

basic_string::s ubstr
basic_string substr(size_typ e off = 0,
size_type count = npos) const;
The member function returns an object whose controlled sequence is a copy of
up to count elements of the controlled sequence beginning at position off.

It returns by value! AAAAAAaaahhhhhh hh! throw Inefficiency(); !


Yeah, std::string is like that. But the alternative is far more
complex. (check out the string classes used in Mozilla)

-josh

Jul 22 '05 #9
> auto_ptr<AnyCla ss> Blah()
{
auto_ptr<AnyCla ss> poo( new AnyClass );

return poo;
}

Maybe I'm being dense but std::auto_ptr gets
removed when it exits scope, no?
int main()
{
auto_ptr<AnyCla ss> const &milk = Blah();


How can this work if the memory is overwritten by something else?
Jul 22 '05 #10

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

Similar topics

2
2921
by: Mountain Man | last post by:
Hi, I'm having trouble with the foreach function. I'm using it twice inside a user defined function with two different arrays, and in the second instance it's returning the value of the first key for all the keys. My code is shown below and the problem areas are marked with comments. In case you're wondering, this script is for generating sticky checkboxes that include an event handler. Many thanks to anyone who can help.
5
2173
by: Anthony Papillion II | last post by:
Hello Everyone, I have been having fits with a simple PHP script and I'm hoping it's something that someone here can help me with. Basically, when I execute the SQL statement directly on the MySQL CLI, it returns. But when I run the same statement through the following PHP script, I *think* it returns an empty set. I say I think because the if(mysql_num_rows($recset) > 0){} block is executed. But when I try to retreive values stored...
3
4505
by: Jochen Zeischka | last post by:
I'm puzzled. When compiling this: template<class ValRes, class Val1, class Val2> Veld<ValRes>& mult(Veld<ValRes>& res, const Veld<Val1>& v1, const Veld<Val2>& v2) { // something return res; } the compiler says:
28
3692
by: Yevgen Muntyan | last post by:
Hey, Consider the following code: void func (void) { } void func2 (void) {
6
2817
by: Kavya | last post by:
I was reading a book Test Your C++ Skills by Yashwant Kanetkar. There was a question in it Ques: Why constructors do not have return values? Ans :Constructors are called whenever an object is created. And there can never exist a situation where we want to return a value at the time of creation of an object. I don't understand why author says that. What if I want to check whether the object is successfully created. We
6
1083
by: rowe_newsgroups | last post by:
I just noticed this about value types and return values, and it kind of bugs me that the compiler won't treat it as an error, even with Option Strict On. Try this out: Option Strict On Public Class MyClass
5
1697
by: littlevikinggirl | last post by:
Hi, I posted a badly worded question last week so got no replies and am still struggling to figure out the problem myself. I have a table containing two fields, Location and Serial Number. I want to display some of the serial number values on a form which will have a diagram overlaid (to map out the "locations"). I have been trying to write an If statement in the controlsource properties of the text boxes to say "if location=position1...
4
2394
omerbutt
by: omerbutt | last post by:
hi there i am making an application in which i have a drop down menu which onchange passes a value(this.value) to a js function which gets the value and calls an ajax routine and passes that value to a php page and then takes back the response ,i have done it all but now i was trying to encrypt the information or the string or the value that is passed through the drop down menu and concatinated with the url and passed to that page and then on...
2
3169
by: chuckzter | last post by:
I'm in a bit of a pickle here. I need to pass the variable @uname which gets a value from a text box to a statement on one of my stored procedures in SQL server and return an output on my form. Here is the code: in .net cmd = New SqlCommand cmd.CommandText = "sp_TransData" cmd.CommandType = CommandType.StoredProcedure cmd.Parameters.Add("@unamex",SqlDbType.VarChar,15)
0
9387
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10148
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10002
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9823
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7368
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6643
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5270
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3917
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2794
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.