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

Ultimate Efficiency


Your program begins at:

int main(void);
Now, in main, you want to call a function. This particular function you want
to call defines a local object of type Taste, and then returns this local
object by value.

In main, having called this function, what you want to do is bind a
reference to the object returned from Taste and then continue on and use it
just as if it were defined in main as a local object.

The first restriction here is that the Standard declares that you can bind
the object returned from a function only to a *const* reference.

Altogether, you want just 1 object to be created. No temporaries. No copies.
But... in actual fact you're going to have 3 objects:

1: The local variable defined in the function

2: The temporary returned

3: You'll have to create another object in main and copy the temporary so as
to alleviate the constness.
I wrote the following code a few mins ago and it compiles and runs grand.
I've tried my best to make the code as non-tedious as possible to read, so
please just give it a glance over:
#include <iostream>

class Taste
{
public:

static unsigned char amount_ever;

static unsigned char amount_currently;
int mouth;

unsigned char age;
void Swallow(void)
{
mouth += 2;
}

Taste(void) : mouth(7), age(14)
{
++amount_ever;
++amount_currently;
}

Taste(Taste& original)
{
mouth = original.mouth;
age = original.age;

++amount_ever;
++amount_currently;
}

~Taste(void)
{
--amount_currently;
}
};
unsigned char Taste::amount_ever = 0;

unsigned char Taste::amount_currently = 0;
Taste Powder(void)
{
Taste cream;

cream.age = 4;

cream.Swallow();

return cream;
}
int main(void)
{
const Taste& yacht = Powder();

Taste& boat = const_cast<Taste&>(yacht);
//Now we have what we wanted, a local variable in main.

boat.age = 12;

boat.Swallow();

std::cout << "Amount ever: " << (int)Taste::amount_ever << std::endl
<< "Amount currently: " << (int)Taste::amount_currently
<< std::endl;

std::system("PAUSE");

}

Now first thing's first:

I'm going to presume that casting away that constness and editing the object
is undefined behaviour.
Can anyone come up with any argument as to why the hell you've to bind to a
*const* reference in the first place?! I'll wait for an answer to this
question before I decide for myself if casting away the constness is
"moral".
Moving on:

With the above code, by casting away the constness, I was aiming for
amount_ever == 2. To my delight, it came up 1!!
Obviously, *my* compiler has not created a temporary, it has returned the
actual local object defined in the function. Which leads me to...
Why the hell is this "optimization" compiler behaviour, as opposed to
"run-of-the-mill" compiler behaviour?!! Can anyone supply me with any
arguments as to why a function should copy the local variable and then
return the copy, as opposed to just returning the local variable itself?!
Here's my thoughts:

My objective is very clear. In my mind, I know and trully believe that I
should be able to do what I want to do with just the 1 object, as opposed to
3! Without regard to the Standard, I believe that C++ as an excellent
programming language should be able to achieve this, that it should be "run-
of-the-mill" compiler behaviour, as opposed to "optimization" compiler
behaviour.

-JKop
Jul 22 '05 #1
24 1630
JKop wrote:
Your program begins at:

int main(void);
Now, in main, you want to call a function. This particular function you want
to call defines a local object of type Taste, and then returns this local
object by value.

In main, having called this function, what you want to do is bind a
reference to the object returned from Taste and then continue on and use it
just as if it were defined in main as a local object.

The first restriction here is that the Standard declares that you can bind
the object returned from a function only to a *const* reference.

Altogether, you want just 1 object to be created. No temporaries. No copies.
But... in actual fact you're going to have 3 objects:

1: The local variable defined in the function

2: The temporary returned

3: You'll have to create another object in main and copy the temporary so as
to alleviate the constness.
Or you can pass your object from main by reference. Did you forget that?


Now first thing's first:

I'm going to presume that casting away that constness and editing the object
is undefined behaviour.
Can anyone come up with any argument as to why the hell you've to bind to a
*const* reference in the first place?! I'll wait for an answer to this
question before I decide for myself if casting away the constness is
"moral".

By casting away the constness, you use a non-const reference to a
temporary which is going to be destroyed at the end of yacht scope. Also
this kind of hackery means that the programmer doesn't know exactly what
he wants to do.



Moving on:

With the above code, by casting away the constness, I was aiming for
amount_ever == 2. To my delight, it came up 1!!
Obviously, *my* compiler has not created a temporary, it has returned the
actual local object defined in the function. Which leads me to...
Why the hell is this "optimization" compiler behaviour, as opposed to
"run-of-the-mill" compiler behaviour?!! Can anyone supply me with any
arguments as to why a function should copy the local variable and then
return the copy, as opposed to just returning the local variable itself?!

Why did you expect it to be 2? The temporary should have the value 1 for
both amount_ever ans amount_currently.
The local variable is destroyed at the end of its scope. Anything else
would be against C++ rules.


Here's my thoughts:

My objective is very clear. In my mind, I know and trully believe that I
should be able to do what I want to do with just the 1 object, as opposed to
3!

My suggestion is to have a slow, thorough read of an up to date ISO C++
book.
Without regard to the Standard, I believe that C++ as an excellent
programming language should be able to achieve this, that it should be "run-
of-the-mill" compiler behaviour, as opposed to "optimization" compiler
behaviour.


:-) If you have space/run-time efficiency concerns you should pass by
reference (using pointers or references). It has nothing to do with C++
but with the proper use of it.


Regards,

Ioannis Vranos
Jul 22 '05 #2
Ioannis Vranos posted:
Or you can pass your object from main by reference. Did you forget
that?

The function's already written. Look at it from that point of view.

I think it's cleaner that the function itself should have the obligation of
declaring the variable and giving it back. You have the choice to just let
the returned object die, or prolong its life by binding it to a reference.

By casting away the constness, you use a non-const reference to a
temporary which is going to be destroyed at the end of yacht scope.

Exactly my intention. boat and yacht have the same scope in anyway, so
there's no problem there.

Why did you expect it to be 2? The temporary should have the value 1
for both amount_ever ans amount_currently.

The temporary should?

amount_ever and amount_currently are static

Tasete::amount_ever

I was expecting it to be 2 because my Powder function "should" have made a
copy of its local object and then returned the copy, aka a temporary. This
would bring the count to 2.

The local variable is destroyed at the end of its scope. Anything else
would be against C++ rules.

First you said that amount_ever should be 1.
Now you're saying that it would be against C++ rules to return the local
object, indicating that the local variable should be copied to a temporary
and the temporary be returned. This brings the count to 2.

A) No temporary. Return local variable. amount_ever = 1

B) Create temporay. Return temporary. amount_ever = 2
-JKop
Jul 22 '05 #3
JKop <NU**@NULL.NULL> wrote in news:w8*****************@news.indigo.ie:
Ioannis Vranos posted:
Or you can pass your object from main by reference. Did you forget
that?

The function's already written. Look at it from that point of view.

I think it's cleaner that the function itself should have the
obligation of declaring the variable and giving it back. You have the
choice to just let the returned object die, or prolong its life by
binding it to a reference.


Or why not:

Taste yacht(Powder());

And let the Return Value Optimization deal with the extra copies of Taste
which can be eliminated?

Jul 22 '05 #4
JKop wrote:
The function's already written. Look at it from that point of view.
Then the library maker must have a slow, thorough read of an up to date
ISO C++ book, as I have been doing myself too.
Another alternative could be the function to create the object on the
free store and return a pointer to it.

In any case, what you have done is not used for objects having large
space/time costs.
I think it's cleaner that the function itself should have the obligation of
declaring the variable and giving it back. You have the choice to just let
the returned object die, or prolong its life by binding it to a reference.

All are a matter of logic. If you are expecting that the function has
the obligation to create that type of object, then you should make it
create it on the free store and return it back to the caller.
The temporary should?

amount_ever and amount_currently are static

Tasete::amount_ever

I was expecting it to be 2 because my Powder function "should" have made a
copy of its local object and then returned the copy, aka a temporary. This
would bring the count to 2.
Ok I got a head ache, let's use this simpler code for reference:
#include <iostream>
#include <cstdlib>

class test
{
public:
static int counter;

test() { ++counter; }
};

int test::counter=0;
test somefunc()
{
test a;

return a;
}

int main()
{
using namespace std;

somefunc();

cout<<test::counter<<endl;

system("pause");
}
G++ produces:

C:\c>temp
1
Press any key to continue . . .
MSVC++ produces:

2
Press any key to continue . . .

Obviously G++ performs an optimisation and uses the same object instead
of creating a temporary one. Strictly speaking it is a G++ bug, however
probably its makers considered that this optimisation has not real-life
implications.

Strictly ISO C++ speaking, you can report it as a defect.
First you said that amount_ever should be 1.
Now you're saying that it would be against C++ rules to return the local
object, indicating that the local variable should be copied to a temporary
and the temporary be returned. This brings the count to 2.

Yes, it should be 2. At the first time I was confused with your
redundant counter usage.


Regards,

Ioannis Vranos
Jul 22 '05 #5
> class test
{
public:
static int counter;

test() { ++counter; }
test(test& original)
{
++counter;
}

//It's the copies we're woried about!
};

int test::counter=0;

Jul 22 '05 #6

"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message
news:cb**********@ulysses.noc.ntua.gr...
Ok I got a head ache, let's use this simpler code for reference:
#include <iostream>
#include <cstdlib>

class test
{
public:
static int counter;

test() { ++counter; }
you forgot
test(const test&)
{
++counter;
} };

int test::counter=0;
test somefunc()
{
test a;

return a;
}

int main()
{
using namespace std;

somefunc();

cout<<test::counter<<endl;

system("pause");
}
G++ produces:

C:\c>temp
1
Press any key to continue . . .
MSVC++ produces:

2
Press any key to continue . . .
I presume that you have copy constructor
in compiled version.


Obviously G++ performs an optimisation and uses the same object instead
of creating a temporary one. Strictly speaking it is a G++ bug, however
probably its makers considered that this optimisation has not real-life
implications.

Strictly ISO C++ speaking, you can report it as a defect.


I don't think so. Check out 12.18.15:

"
Whenever a temporary class object is copied using a copy constructor, and
this object and the copy have the same cvunqualified
type, an implementation is permitted to treat the original and the copy as
two different ways of referring to the same object and not perform a copy at
all, even if the class copy constructor or destructor have
side effects. For a function with a class return type, if the expression in
the return statement is the name of a local object, and the cvunqualified
type of the local object is the same as the function
return type, an implementation is permitted to omit creating the temporary
object to hold the function return value, even if the class
copy constructor or destructor has side effects. In these cases, the object
is destroyed at the later of times when the original and the copy would have
been destroyed without the optimization.

111) [Example:

class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
Thing operator=(const Thing&);
void fun();
};

Thing f() {
Thing t;
return t;
}

Thing t2 = f();

Here t does not need to be copied when returning from f. The return value of
f may be constructed directly into the object t2. ]

"

Greetings, Bane.



Jul 22 '05 #7
Branimir Maksimovic posted:
I don't think so. Check out 12.18.15:

"
Whenever a temporary class object is copied using a copy constructor,
and this object and the copy have the same cvunqualified
type, an implementation is permitted to treat the original and the copy
as two different ways of referring to the same object and not perform a
copy at all, even if the class copy constructor or destructor have
side effects. For a function with a class return type, if the
expression in
the return statement is the name of a local object, and the
cvunqualified type of the local object is the same as the function
return type, an implementation is permitted to omit creating the
temporary object to hold the function return value, even if the class
copy constructor or destructor has side effects. In these cases, the
object
is destroyed at the later of times when the original and the copy would
have been destroyed without the optimization.

This pleases me.

But... that doesn't address the issue of a temporary being made in the first
place when one is not necesary! For example:

int monkey(void)
{
return 22;
}

In the above, a temporary definitely is necessary.

int monkey(void)
{
int cow = 22;

return cow;
}

In the above, a temporary is unncecessary. It can simply just return cow.
But does it...? And what does the Standard have to say about it?

111) [Example:

class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
Thing operator=(const Thing&);
void fun();
};

Thing f() {
Thing t;
return t;
}

Thing t2 = f();

Here t does not need to be copied when returning from f. The return
value of f may be constructed directly into the object t2. ]


Just so you know, the operator= is never called in your code.
-JKop
Jul 22 '05 #8

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

But... that doesn't address the issue of a temporary being made in the first place when one is not necesary! For example:

int monkey(void)
{
return 22;
}

In the above, a temporary definitely is necessary.
What temporary? As I understand when talking about
temporaries we are thinking about instances of
structs/classes with constructors.
Above can be compiled with just two assembly
instructions:
move 22 to register and return from function.

int monkey(void)
{
int cow = 22;

return cow;
}

In the above, a temporary is unncecessary. There is no temporary in this case either.
It can be compiled with just two assembly
instructions as previous example.
It can simply just return cow.
But does it...?
And what does the Standard have to say about it?
"
[basic.stc.auto] 3.7.2 Automatic storage duration

1 Local objects explicitly declared auto or register or not explicitly
declared static or extern have automatic storage duration. The storage for
these objects lasts until the block in which they are created exits.

2 [Note: these objects are initialized and destroyed as described in 6.7. ]

3 If a named automatic object has initialization or a destructor with side
effects, it shall not be destroyed before the end of its block, nor shall it
be eliminated as an optimization even if it appears to be unused, except
that a class object or its copy may be eliminated as specified in 12.8.

"

It is clear that return value optimization only refers to
classes/structs with constructors/destructors

111) [Example:

class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
Thing operator=(const Thing&);
void fun();
};

Thing f() {
Thing t;
return t;
}

Thing t2 = f();

Here t does not need to be copied when returning from f. The return
value of f may be constructed directly into the object t2. ]


Just so you know, the operator= is never called in your code.


This is just one of two forms of initialization.

"

The initialization that occurs in argument passing, function return,
throwing an exception (15.1), handling an exception (15.3), and
braceenclosed initializer lists (8.5.1) is called copyinitialization
and is equivalent to the form

T x = a;

The initialization that occurs in new expressions (5.3.4), static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and base
and member initializers (12.6.2) is called directinitialization
and is equivalent to the form

T x(a);

"
Greetings, Bane.


Jul 22 '05 #9
JKop wrote:
//It's the copies we're woried about!


Actually I copied and pasted the wrong code but with the right results.
The correct one:
#include <iostream>
#include <cstdlib>

class test
{
public:
static int counter;

test() { ++counter; }
test(const test &x) { ++counter; }
};

int test::counter=0;
test somefunc()
{
test a;

return a;
}

int main()
{
using namespace std;

const test&r=somefunc();

cout<<test::counter<<endl;

system("pause");
}

It produces 2 with MSVC++ and 1 with G++.


Regards,

Ioannis Vranos
Jul 22 '05 #10
Branimir Maksimovic wrote:

I don't think so. Check out 12.18.15:

12.8.15. It took few time to track it down.

"
Whenever a temporary class object is copied using a copy constructor, and
this object and the copy have the same cvunqualified
type, an implementation is permitted to treat the original and the copy as
two different ways of referring to the same object and not perform a copy at
all, even if the class copy constructor or destructor have
side effects. For a function with a class return type, if the expression in
the return statement is the name of a local object, and the cvunqualified
type of the local object is the same as the function
return type, an implementation is permitted to omit creating the temporary
object to hold the function return value, even if the class
copy constructor or destructor has side effects. In these cases, the object
is destroyed at the later of times when the original and the copy would have
been destroyed without the optimization.


Well, there is always something new to learn. Thanks for the
information. :-)


Regards,

Ioannis Vranos
Jul 22 '05 #11

"JKop" <NU**@NULL.NULL> wrote in message
news:r5*****************@news.indigo.ie...
Branimir Maksimovic posted:
int monkey(void)
{
int cow = 22;

return cow;
}

In the above, a temporary is unncecessary. It can simply just return cow.


Ah, think I know what you mean by temporary.

const int& tmpref = monkey();

in this case termorary variable must be created in order to
initialize reference with it.

int notemp = monkey();

in this case there is no temporary variable created.

Greetings, Bane.

Jul 22 '05 #12
Branimir Maksimovic wrote:
This is just one of two forms of initialization.

"

The initialization that occurs in argument passing, function return,
throwing an exception (15.1), handling an exception (15.3), and
braceenclosed initializer lists (8.5.1) is called copyinitialization
and is equivalent to the form

T x = a;

The initialization that occurs in new expressions (5.3.4), static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and base
and member initializers (12.6.2) is called directinitialization
and is equivalent to the form

T x(a);

"


Doesn't the above mean that the temporary returned from a function call
is created using operator=() instead of copy constructor?!
However as far as I know(?) the copy constructor is used in this case.


Regards,

Ioannis Vranos
Jul 22 '05 #13
Ioannis Vranos wrote:

Branimir Maksimovic wrote:
This is just one of two forms of initialization.

"

The initialization that occurs in argument passing, function return,
throwing an exception (15.1), handling an exception (15.3), and
braceenclosed initializer lists (8.5.1) is called copyinitialization
and is equivalent to the form

T x = a;

The initialization that occurs in new expressions (5.3.4), static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and base
and member initializers (12.6.2) is called directinitialization
and is equivalent to the form

T x(a);

"
Doesn't the above mean that the temporary returned from a function call
is created using operator=() instead of copy constructor?!


No.

However as far as I know(?) the copy constructor is used in this case.


Right. (Object creation is always handled through some constructor. operator=
would need an already existing object, which is not there when the object
gets born)

In

T x = a

no operator= is involved. It is equivalent to

T x( T(a) );

First create a temporary from 'a' by taking a constructor which
takes an 'a', then use that temporary in a copy constructor to
create the final object.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #14

"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message
news:10**************@athnrd02.forthnet.gr...
Branimir Maksimovic wrote:
This is just one of two forms of initialization.

"

The initialization that occurs in argument passing, function return,
throwing an exception (15.1), handling an exception (15.3), and
braceenclosed initializer lists (8.5.1) is called copyinitialization
and is equivalent to the form

T x = a;

The initialization that occurs in new expressions (5.3.4), static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called directinitialization
and is equivalent to the form

T x(a);

"
Doesn't the above mean that the temporary returned from a function call
is created using operator=() instead of copy constructor?!


No. It is initialization of object, not assignment.

T x(a); <=> T x = a;


However as far as I know(?) the copy constructor is used in this case.


Yes, but not always.

T func()
{
T tmp;
//...
return tmp;
}

If tmp is optimised out (RVO),
return value temporary is constructed with default constructor
so copy constructor is never called.

Greetings, Bane.


Jul 22 '05 #15

"Branimir Maksimovic" <bm***@eunet.yu> wrote in message
news:cb**********@news.eunet.yu...

T x(a); <=> T x = a;


In case that typeof a is T

Jul 22 '05 #16
Branimir Maksimovic posted:

"JKop" <NU**@NULL.NULL> wrote in message
news:r5*****************@news.indigo.ie...
Branimir Maksimovic posted:
int monkey(void)
{
int cow = 22;

return cow;
}

In the above, a temporary is unncecessary. It can simply just return
cow.


Ah, think I know what you mean by temporary.

const int& tmpref = monkey();

in this case termorary variable must be created in order to
initialize reference with it.

int notemp = monkey();

in this case there is no temporary variable created.


Nope, it's not the calling function that's creating the temporary, but the
*called* function.

-JKop

Jul 22 '05 #17

"JKop" <NU**@NULL.NULL> wrote in message
news:8o*****************@news.indigo.ie...
Branimir Maksimovic posted:

"JKop" <NU**@NULL.NULL> wrote in message
news:r5*****************@news.indigo.ie...
Branimir Maksimovic posted:
int monkey(void)
{
int cow = 22;

return cow;
}

In the above, a temporary is unncecessary. It can simply just return
cow.


Ah, think I know what you mean by temporary.

const int& tmpref = monkey();

in this case termorary variable must be created in order to
initialize reference with it.

int notemp = monkey();

in this case there is no temporary variable created.


Nope, it's not the calling function that's creating the temporary, but the
*called* function.


Just check out assembly code created from compiler.
How and where do you think temporary variable is created in
called function?

Greetings, Bane.
Jul 22 '05 #18
JKop wrote:
//It's the copies we're woried about!


Today there was a much with my Usenet server and I do not know how much
of my messages shown up, but to make sure that this one is shown, I am
reposting it:

Actually I copied and pasted the wrong code but with the right results.
The correct one:
#include <iostream>
#include <cstdlib>

class test
{
public:
static int counter;

test() { ++counter; }
test(const test &x) { ++counter; }
};

int test::counter=0;
test somefunc()
{
test a;

return a;
}

int main()
{
using namespace std;

const test&r=somefunc();

cout<<test::counter<<endl;

system("pause");
}

It produces 2 with MSVC++ and 1 with G++.


Regards,

Ioannis Vranos
Jul 22 '05 #19
Branimir Maksimovic posted:
Just check out assembly code created from compiler.
How and where do you think temporary variable is created in
called function?

I don't know assembly!
-JKop
Jul 22 '05 #20
"Branimir Maksimovic" <bm***@eunet.yu> wrote:
"JKop" <NU**@NULL.NULL> wrote:
Branimir Maksimovic posted:
>
> int monkey(void)
> {
> int cow = 22;
> return cow;
> }
>
> In the above, a temporary is unncecessary. It can simply just return
> cow.

Ah, think I know what you mean by temporary.
"temporary" means an object without a name.
const int& tmpref = monkey();

in this case termorary variable must be created in order to
initialize reference with it.

int notemp = monkey();

in this case there is no temporary variable created.

Yes there is. The call to monkey() returns a temporary variable of type int.
Then notemp is initialized from this temporary int, and then the temporary
int is destroyed.
Just check out assembly code created from compiler.
How and where do you think temporary variable is created in
called function?


Probably your compiler will use a register for the temporary int.
monkey() would assign 22 to this register, and then the calling function
would copy the value from that register into the memory location of notemp.

Of course, the compiler could optimise this out entirely, or in fact use
any other assembly instructions that it likes. That doesn't change
what is happening theoretically.
Jul 22 '05 #21
On Wed, 23 Jun 2004 10:35:56 +0000, JKop wrote:
Branimir Maksimovic posted:
Just check out assembly code created from compiler.
How and where do you think temporary variable is created in
called function?


I don't know assembly!


Learn.

<http://www.drpaulcarter.com/pcasm/>

</OT>

--
Some say the Wired doesn't have political borders like the real world,
but there are far too many nonsense-spouting anarchists or idiots who
think that pranks are a revolution.

Jul 22 '05 #22

"Old Wolf" <ol*****@inspire.net.nz> wrote in message
news:84**************************@posting.google.c om...
"Branimir Maksimovic" <bm***@eunet.yu> wrote:
"JKop" <NU**@NULL.NULL> wrote:
Branimir Maksimovic posted:
>>
>> int monkey(void)
>> {
>> int cow = 22;
>> return cow;
>> }
>>
> ....... > int notemp = monkey();
>
> in this case there is no temporary variable created.

Yes there is. The call to monkey() returns a temporary variable of type

int. Then notemp is initialized from this temporary int, and then the temporary
int is destroyed.
I don't think so:
"
[stmt.return] 6.6.3 The return statement

1 A function returns to its caller by the return statement.

2 A return statement without an expression can be used only in functions
that do not return a value, that is, a function with the return type void, a
constructor (12.1), or a destructor (12.4). A return statement with an
expression of nonvoid type can be used only in functions returning a value;
the value of the expression is returned to the caller of the function.
The expression is implicitly converted to the return type of the function
in which it appears. A return statement can involve the construction and
copy of a temporary object
"

As you can see this clearly proves my point.
return statement always returns value, not temporary variable.
It *can* involve the construction and copy of tmp object.
So there is not *must*.
Just check out assembly code created from compiler.
How and where do you think temporary variable is created in
called function?
Probably your compiler will use a register for the temporary int.
monkey() would assign 22 to this register, and then the calling function
would copy the value from that register into the memory location of

notemp.
Of course, the compiler could optimise this out entirely, or in fact use
any other assembly instructions that it likes. That doesn't change
what is happening theoretically.


T func()
{
T tmp;
// ....
return t;
}

T x = func();

In case that x cannot fit in register,
implementation can just pass address of x to func, which will construct
tmp in place of it, effectively returning nothing, because standard says
so.
In case that x can fit in register,
implementation can just assign *value* returned from function.

Theoretically func returns value, not temporary object, so everything is
allowed.

Greetings, Bane.

P.S.
me advocate ? nooooooo :(

Jul 22 '05 #23
"Branimir Maksimovic" <bm***@eunet.yu> wrote:

[I won't reply to the first half of the post, except to say that I think
we are saying the same thing: "The compiler can do X" and "The compiler
always does X and sometimes optimises it out", surely amount to the
same thing]
T func()
{
T tmp;
// ....
return t;
}

T x = func();

In case that x cannot fit in register,
implementation can just pass address of x to func, which will construct
tmp in place of it, effectively returning nothing, because standard says
so.
In case that x can fit in register,
implementation can just assign *value* returned from function.
This is called NRVO (named return value optimisation). As you mentioned,
the compiler *can* do this , but it does not have to. A standards-
conforming compiler could call one default constructor and two
copy constructors and two destructors, for the above example.
Note that the above code *must not* compile on a standards-conforming
compiler if there is not an accessible copy constructor for T.
Theoretically func returns value, not temporary object, so everything is
allowed.


A temporary object *is* a value (or, pedantically, the value of the
[rvalue] expression "func()" is a temporary object of type T).
For example, if in the above code 'func' was in a different
translation unit, then it obviously couldn't perform RVO, eg. if
the caller went:
func().foo();
Jul 22 '05 #24
JKop wrote:
Branimir Maksimovic posted:
Just check out assembly code created from compiler.
How and where do you think temporary variable is created in
called function?


I don't know assembly!


If you are really so concerned about efficiency you should learn it.
Reading the assembler code generated by the compiler can be really
instructive. It will learn you what your compiler can and cannot
optimize. With that knowledge you can avoid pointless optimization
efforts that often do more harm than good (in many ways). Optimization
attempts based on just assumptions are almost never a good idea. I have
seen too many times people writing very ugly code in the assumption that
it will run faster, while often it makes no differences at all or is
even slower than the cleanly coded version.

BTW. if you only want to be able to read assembly code it is really not
that hard; it is a lot simpler than the C++ language. The effort may be
worthwhile if your intention is to write high performance code. But if
you are only interested in doing GUI or database stuff...don't bother.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
Jul 22 '05 #25

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

Similar topics

50
by: Edward K. Ream | last post by:
I would like to say a few (actually more than a few) words here about some recent discoveries I have made concerning the interaction of Leo and Python. If you don't want to hear an inventor enthuse...
24
by: omlet | last post by:
omlet v4) wrote in message Dear DBA, You are cordially invited to test and review our windows native and 100% pure Java Oracle 9i/8i Monitoring Application (OMLET). OMLET is the Ultimate Visual...
0
by: Mirek Fidler | last post by:
Ultimate++ is the new generation C++ Windows/Linux open-source development platform. By utilizing of new ideas Ultimate++ achieves significant reduction of code complexity for most applications...
0
by: Mirek Fidler | last post by:
Ultimate++ 0.98.7 (http://upp.sourceforge.net) was released. Ultimate++ is an attempt to provide the optimal Windows/Linux development platform based on C++. By utilizing of new ideas in C++...
335
by: extrudedaluminiu | last post by:
Hi, Is there any group in the manner of the C++ Boost group that works on the evolution of the C language? Or is there any group that performs an equivalent function? Thanks, -vs
19
by: vamshi | last post by:
Hi all, This is a question about the efficiency of the code. a :- int i; for( i = 0; i < 20; i++ ) printf("%d",i); b:- int i = 10;
9
by: OldBirdman | last post by:
Efficiency I've never stumbled on any discussion of efficiency of various methods of coding, although I have found posts on various forums where individuals were concerned with efficiency. I'm...
1
by: Chris Botha | last post by:
I upgraded from Vista Home Premium to Ultimate. With Home Premium there is no Windows Authentication for IIS - I googled that it is available under Ultimate and upgraded to Ultimate. However, when...
2
by: =?Utf-8?B?TG9yZW4=?= | last post by:
I have a brand new Dell computer right out of the box. It was purchased with Windows Vista Basic. I have also separately purchased Windows Vista Ultimate and I want to install it on this new...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
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
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
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
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...
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...
0
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...

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.