GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 03-Jun-2007, 22:23
meili100 meili100 is offline
Junior Member
 
Join Date: Feb 2007
Posts: 37
meili100 has a little shameless behaviour in the past

A question about 'Return Value'


I have the following code just for fun

CPP / C++ / C Code:
class Base{
public:
	Base(){cout<<"Constructor"<<endl;}
	Base(const Base &obj){cout<<"Copy Constructor"<<endl;}
	Base & operator=(const Base& obj){
		cout<<"Operator="<<endl;
		return *this;
	}
};

Base foo(){
	Base x;
	return x;
}

void main(){
	Base tmp = foo();
}

=================
Why the outputs are only

Constructor
Copy Constructor

But I think the outputs should be:
Constructor
Copy Constructor // from return x
Copy Constructor // from Base tmp = foo();
  #2  
Old 04-Jun-2007, 03:41
Peter_APIIT Peter_APIIT is offline
Regular Member
 
Join Date: May 2007
Location: Malaysia
Posts: 545
Peter_APIIT can only hope to improve
Thumbs up

Re: A question about 'Return Value'


I not familiar with this pointer, copy constructor and assignment.

I guess the x value and the function should inside the class.

I also want to know what is this pointer. The function of this pointer is returned the object which belongs to the function. (Just Guess)


Thanks for your help.

Your help is greatly appreciated by me and others.
  #3  
Old 04-Jun-2007, 08:30
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 5,311
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: A question about 'Return Value'


Quote:
Originally Posted by meili100
Why the outputs are only

Constructor
Copy Constructor


To get some insight, I respectfully suggest that you can investigate things that puzzle you rather than trying to get someone else to explain it.

For example try the following:

CPP / C++ / C Code:
#include <iostream>

using namespace std;

class Base {
  public:
    Base() {
        cout << "Constructor" << endl;
    }
    Base(const Base & obj) {
        cout << "Copy Constructor" << endl;
    }
    Base & operator=(const Base & obj) 
    {
        cout << "Operator=" << endl;
        return *this;
    }
    ~Base() {
        cout << "Destructor" << endl;
    }
};

Base foo()
{
    Base x;
    cout << "foo() is returning" << endl;
    return x;
}

int main()
{
    cout << "Before tmp=foo() declaration" << endl << endl;
    Base tmp = foo();
    cout << endl << "After tmp=foo() declaration" << endl;

    return 0;
}
Output with program compiled by Borland and Microsoft compilers on my Windows XP system:
Code:
Before tmp=foo() declaratio Constructor foo() is returning Copy Constructor Destructor After tmp=foo() declaration Destructor

The initialization statement for tmp apparently calls foo(), which calls the constructor to create a temporary object. Then it calls the copy instructor with the value returned by foo() and destructs the temporary object.

An interesting thing (to me at least) is what happens when the program is compiled with GNU g++. The output is

Code:
Before tmp=foo() declaration Constructor foo() is returning After tmp=foo() declaration Destructor

g++ is apparently smart enough to realize that it's silly to call a constructor for a temporary object and then use its value to call another constructor and then destruct the temporary object. So, its code just does everything in one step! See footnote.

Want more? Then try the following:
CPP / C++ / C Code:
#include <iostream>

using namespace std;

class Base {
  public:
    Base() {
        cout << "Constructor" << endl;
    }
    Base(const Base & obj) {
        cout << "Copy Constructor" << endl;
    }
    Base & operator=(const Base & obj) 
    {
        cout << "Operator=" << endl;
        return *this;
    }
    ~Base() {
        cout << "Destructor" << endl;
    }
};

Base foo()
{
    Base x;
    cout << "foo() is returning" << endl;
    return x;
}

int main()
{
    cout << "Before tmp2(foo()) declaration" << endl << endl;
    Base tmp2(foo());
    cout << endl << "After tmp2(foo()) declaration" << endl;

    return 0;
}

Now, believe it or not, I get three different results with the three compilers

Borland:
Code:
Before tmp2(foo()) declaration Constructor foo() is returning Copy Constructor Destructor Copy Constructor Destructor After tmp2(foo()) declaration Destructor

Microsoft:
Code:
Before tmp2(foo()) declaration Constructor foo() is returning Copy Constructor Destructor After tmp2(foo()) declaration Destructor

GNU:
Code:
Before tmp2(foo()) declaration Constructor foo() is returning After tmp2(foo()) declaration Destructor

It appears to me that Microsoft and GNU treat the two examples the same, but Borland actually does more work for the second one than for the first. (If I had been guessing, I would have guessed that, if there were any differences between the first example and the second, the second would have been more efficient. Don't ask me why I would have guessed this, and, in particular, don't bet on anything that I or anyone else on this beautiful planet would guess.)


Bottom line: You can investigate and see what your compiler is actually doing with your code. But, and this is important, don't draw general conclusions based on the behavior of a single version of a single compiler. The C++ standard doesn't say what kinds of code must be generated from the source given in the two examples; it only says what the result must be.

So, how the heck can you say "I expected..." when each compiler writer is free to do whatever the heck he/she wants to as long as the final result is the required one? Whatever may seem obvious to you (or me) may or may not be what the compiler actually does.

Regards,

Dave

Footnote: The process of eliminating unnecessary storing and retrieval of objects can be eliminated by even the simplest optimization steps in what we used to call a "peephole" optimizer. Just keep track of whether an object is loaded again after storing it without any destructive steps in between times. Then, simply, don't store it.

I learned this from studying the "Small C" compiler published about a thousand years ago (that's how long ago it seems to me). This was a very primitive compiler for 8088/8086 machines when the world was young and CP/M was the Big Thing and Microsoft compilers cost USD 700 and Borland hadn't hit the scene with USD 50 Turbo Pascal (for CP/M and DOS) and, later, Turbo C (alas, no CP/M---that's when I built my first 8088 system for DOS and abandoned CP/M forever).
 
 

Recent GIDBlogProblems with the Navy (Enlisted) by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Things to Avoid in C/C++ -- gets() , Part 1 WaltP C Programming Language 5 21-Jun-2007 12:13
need help with a console menu system BullBuchanan C++ Forum 6 20-Aug-2006 14:46
Reading non ASCII with read() Atomical C Programming Language 8 13-Sep-2005 14:30
Problem with one variable bretter C++ Forum 1 16-May-2005 07:20
C++ file I/O CronoX C++ Forum 36 09-Mar-2004 17:28

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 19:09.


vBulletin, Copyright © 2000 - 2010, Jelsoft Enterprises Ltd.