473,785 Members | 2,801 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C++ compiler "return" behavior (guru question ;)

Hi all,

I am trying to get my head around what happens if I return a class
object from a function.
It seems C++ (MinGW) does not invoke the copy constructor if I do
something like this:

SomeObj foo()
{
SomeObj X;
// ....
return X;
}

BUT it does create a new object every time the function is invoked, and
it does seem like these objects are usable (I created a little test
program checking this :).
So basically I can go in main:

int main()
{
// ....
SomeObj bar = foo();
SomeObj bar2 = foo();
// for some strange reason the next thing will fail, though:
SomeObj &bar3 = foo();
}

and I will get two different objects back, both valid. (As commented,
the third will fail with some obscure warning about temporary objects -
but there's no copying taking place, so there's no temp object, AFAIK).
Hm.

So I checked something else:

void foobar()
{
SomeObj IamUseless;
}

That object is actually constructed, but destroyed after the function.
Now I am a bit unsure how the C++ compiler can determine EACH TIME
which object gets returned (maybe in the depth of an STL container of
whatever), and which one does NOT, so this has to be destroyed.

Usually I use new() for factories, but I wondered, and I checked. And I
don't get it :) . So maybe there's a guru in here who can help me out
with some background information? ;)
Cheers & thanks,
Axel.

Apr 9 '06
32 2215
Hi Peter,
But it IS a local object. I see nothing confusing about that. What
would be truly confusing would be if assignment created a different
object than copy construction.
Sorry to disagree, but I don't think this is a local object. What I
understand from what was said in the thread this object is available
globally (read: in main) after the function exits, and it is perfectly
legal in being so. So it _looks_ like one, but it is not destroyed
after scope exit, which makes it somewhat not-local in my eyes :) .
(Mind: I am talking about the _object_, not the C++-variable holding it
in the function).
You might call it an optimization, but one employed by all compilers i
know. Still the optimization should not change anything for the reasons
stated above.


Ok, that's a point, so this can be considered safe to use. Thanks :)
Cheers,
Axel.

Apr 10 '06 #11
Ian Collins wrote:
int main()
{
// ....
SomeObj bar = foo();
SomeObj bar2 = foo();
// for some strange reason the next thing will fail, though:
SomeObj &bar3 = foo();


You can't bind a temporary object (the function return) to a non-const
reference. Try

const SomeObj &bar3 = foo();


Wait, now I'm confused. Won't reading the value of bar3 yield
undefined behavior, since it references a temporary that went out of
scope?

Apr 10 '06 #12
What I would like to clarify now is the "style" of that code: Is that
good style, or not?


I think it's bad style to do the following:

SomeClassType object = FuncReturnsByVa lue();

For two reasons:

1) You must rely on an optimization if you don't want any copies.
2) The copy constructor must be public.

There are two workarounds. Here's the less favourable method:

std::auto_ptr<S omeClassType> Func()
{
std::auto_ptr<S omeClassType> p = new SomeClassType;

//Play with the object

return p;
}

int main()
{
std::auto_ptr<S omeClassType> p = Func();
}
The other option, the option which I advocate, is to use a class.

class Manipulator
{
SomeObj object;

Manipulator() : object( whatever )
{
//Play with the object in here
}
}

int main()
{
Manipulator manipulated;
}
-Tomás
Apr 10 '06 #13
Hi Tomas,

still, if you wanted a factory function, you should be able to write
one :) . Sometimes you want to create an object based on certain
external factors. If this action takes place in, say, 23 places in your
code, writing a function for that would be normal.

@Squeamizh: Confused is what I was. Still, as I understood, what we
face here is a so-called "return-value-optimization". In that case the
compiler recognizes that this object you return gets assigned to a ...
variable in the calling (!) code, so it will perform all the actions,
but the resulting object will be global. Or in other words: Doing a

SomeObj obj = foo();

translates to something like:

SomeObj &obj;
if (this_or_that) {
// .... yadda ....
obj = /* something smart */
}
else if (blah ...)
{
//.....
obj = /* whatever */
}
/* basically all your foo-code */

(very, very roughly) explained. And all this because the compiler
actually realizes that the _local_ object gets returned and is to be
used in a wider scope.

Apr 10 '06 #14
Squeamizh wrote:
Ian Collins wrote:
int main()
{
// ....
SomeObj bar = foo();
SomeObj bar2 = foo();
// for some strange reason the next thing will fail, though:
SomeObj &bar3 = foo();


You can't bind a temporary object (the function return) to a non-const
reference. Try

const SomeObj &bar3 = foo();

Wait, now I'm confused. Won't reading the value of bar3 yield
undefined behavior, since it references a temporary that went out of
scope?

Binding it to a const reference keeps it in scope.

--
Ian Collins.
Apr 10 '06 #15
Axel Bock wrote:
Hi Ian,

you're right, this works. But why should that return value be a const?
It isn't.
I have declared const nowhere in the whole thing, and there's no
copying between the return value and the used object in main.
There is copying. The compiler is allowed to perform an
optimization so it does not actually have to move bits around,
but the object management rules of C++ behave as if there is
a copy in all cases (it would be silly if legal code sometimes
worked and sometimes did not work based on whether a
compiler was optimizing or not).
So I would say the function's return value is in fact not a temporary
object,
The return value is a temporary object (aka. an rvalue). The fact that
the compiler may perform an optimization on it, does not change
anything.
and it being const is ... weird. I can modify bar and bar2 all
right ... :)
It isn't const. You can modify it. If you write:
foo().x = 3;
then there is no problem.

The original code was something like:
SomeObj const &bar3 = foo();

bar3 is a const reference. This means that you cannot modify
the referred-to object via this reference. The object itself is not
const.

Here's another example:

int i = 1;
int const &j = i;
j = 2; // illegal
i = 2; // legal

In this case 'i' is not const, even though there is a const
reference to it in existence.

Basically I wonder about the object created in foo(), because should
be on the stack, in my opinion, and should be destroyed after the
function's scope ends.


When you bind a temporary object to a reference, its lifetime
gets extended to match the scope of the reference (ie. the
object won't be destroyed until after the reference name goes
out of scope).

The rationale for not allowing binding non-const references to
temporary objects goes something like this:

void foo(int &i) { ++i; }

long x = 1;
foo(x);
cout << "x is " << x << endl;

You might expect this to output 2 but in fact it outputs 1.
There is no function foo() that takes a long, so the compiler
creates a temporary int which is initialized from x, and binds
this temporary int to 'i'. Then the temporary int is incremented,
and destroyed when foo() returns. The value of x is unchanged
by this. By banning binding of temporary objects to non-const
references, this situation would generate a compiler error.

Apr 10 '06 #16
On 10 Apr 2006 16:08:29 -0700, "Old Wolf" <ol*****@inspir e.net.nz>
wrote:
The compiler is allowed to perform an
optimization so it does not actually have to move bits around,
but the object management rules of C++ behave as if there is
a copy in all cases (it would be silly if legal code sometimes
worked and sometimes did not work based on whether a
compiler was optimizing or not).


The compiler may elide copy constructor and destructor calls even if
they have side effects. In that case the C++ program behaves
differently dependent on the 'optimization', e.g.

class Test {
static int i;
public:
Test (const Test& t) {
++i;
}
// ...
};

The actual value of i is different when the the program is compiled
with RVO (and when RVO kicks in).
IMO, programs should return by value only 'leightweight' value objects
for which the 'savings' of RVO are irrelevant anyway.

Best wishes,
Roland Pibinger
Apr 11 '06 #17

Axel Bock wrote:
Hi Peter,
But it IS a local object. I see nothing confusing about that. What
would be truly confusing would be if assignment created a different
object than copy construction.


Sorry to disagree, but I don't think this is a local object. What I
understand from what was said in the thread this object is available
globally (read: in main) after the function exits, and it is perfectly
legal in being so. So it _looks_ like one, but it is not destroyed
after scope exit, which makes it somewhat not-local in my eyes :) .


Here is a cut down version of your original code

SomeObj foo()
{
SomeObj X;
return X;
}

int main()
{
SomeObj bar = foo();
}

You asked whether this was good style. Compilers don't care about style
- they only care about correctness. A compiler will accept poor style
exactly as readily as good style as long as the code is correct. It is
programmers who care about style.

So what does a programmer see in the above code snippet? There are two
completely separate objects of type SomeObj in the code. One is called
X and is local to the function foo. The other is called bar and is
local to the function main. X is destroyed at the end of foo. bar is
destroyed at the end of main. The programmer can perform SomeObj
operations on X within foo and can perform SomeObj operations on bar
within main. But X can not be accessed within main because it does not
exist there.

So what can a programmer do differently if they know return value
optimisation will be performed? Nothing. There is no code you can write
that would only be correct if return value optimisation were performed.
There is nothing you can write in main to violate the scoping rules
that apply to X and bar if the optimisation is performed. So there is
no problem with this style.

Gavin Deane

Apr 12 '06 #18
In message <11************ **********@e56g 2000cwe.googleg roups.com>, Axel
Bock <ax************ @googlemail.com > writes
Hi Ian,
SomeObj bar = foo();
SomeObj bar2 = foo();const SomeObj &bar3 = foo();

you're right, this works. But why should that return value be a const?
The return value isn't; the reference is. You've tripped over an
arbitrary rule that says "thou shall not bind a temporary to a non-const
reference". It's arbitrary in the sense that deleting it wouldn't cause
inconsistencies elsewhere, but it's often a sign of a misunderstandin g
or a coding error. So imposing the rule probably saves programmers from
more problems than it causes.
I have declared const nowhere in the whole thing, and there's no
copying between the return value and the used object in main.
There is (in effect, though it may not cause the copy constructor to be
called) a copy from the return value to the temporary object that the
reference is bound to.
So I
would say the function's return value is in fact not a temporary
object,
What's its name? If it doesn't have a name, it's temporary.
and it being const is ... weird.
You can always convert a non-const reference to a const one.
I can modify bar and bar2 all
right ... :)
Sure. They are named objects. But bar3 is just a reference to an unnamed
temporary that's about to evaporate. What would be the point of
modifying it? OK, sometimes it would make sense, but that's the
reasoning behind the rule.
Basically I wonder about the object created in foo(), because should be
on the stack, in my opinion, and should be destroyed after the
function's scope ends.

But thanks, that answers one question, although replacing it with
another ;)

cheers,
Axel.


--
Richard Herring
Apr 12 '06 #19
On 12 Apr 2006 04:41:13 -0700, "Gavin Deane" <de*********@ho tmail.com>
wrote:
So what can a programmer do differently if they know return value
optimisation will be performed? Nothing. There is no code you can write
that would only be correct if return value optimisation were performed.
There is nothing you can write in main to violate the scoping rules
that apply to X and bar if the optimisation is performed. So there is
no problem with this style.


The problem is that you ignore possible side effects in the copy
constructor and the destructor.

Regards,
Roland Pibinger
Apr 12 '06 #20

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

Similar topics

9
1635
by: Ximo | last post by:
Hello, I want that the return sentence don't return anything, how can I do it?. If i do only return it returns None, and pass don't run too. Can anyone help me?, thanks. XIMO
32
8877
by: Mike Machuidel | last post by:
Hi, I'm a game developer programming mostly in C and ASM for about 7 years. Today at work a colleague (a C++ programmer) yelled at me I'm a bad C programmer because I use "return(0);" instead of "return 0;". He explained that "return" is not a function but a stament, like I didn't know already. The other colleagues also argreed with him :(. Can someone please explain what's so wrong about using "return" with
10
2620
by: LaEisem | last post by:
On-the-job, I have "inherited" a lot of old C language software. A question or two about when "casting" of null pointer constants is needed has occurred during behind-the-scenes cleanup of some of that software. That subject seems not to be addressed, at least not directly, in the C FAQ where FAQ 5.2 seems most relevant. References: * C FAQ 5.2 Null pointers (Including conditions where "casting" of null pointer...
15
6733
by: Greenhorn | last post by:
Hi, when a function doesn't specify a return type ,value what value is returned. In the below programme, the function sample()is returning the value passed to 'k'. sample(int); main() { int i = 0,j; j = sample(0);
1
1882
by: Holger (David) Wagner | last post by:
Hi there, we have an application which is built with several ASCX controls some of which contain form elements (e.g. Textboxes, Buttons etc.) For example: in the top section (one ascx-control), there is a textbutton in which the user can enter a string to search for. There's link button right next to that textbutton. Then, in the "content section" (another ascx-control), there may be a login-dialog which prompts the user for...
0
9645
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10155
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...
1
10095
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9953
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...
0
8978
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7502
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
6741
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
5513
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2881
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.