Article source: blog.chinaunix.net/uid-2081625…

If the function’s passing arguments and return values are objects, what details can happen that we haven’t noticed?

I have done the following experiments in VS2008 and made a simple analysis. If there are any deficiencies or inaccuracies, you are welcome to clap bricks. I will correct the relevant content in time.

\

The function is passed an object.

  1. #include \

  2. #include \

  3. using namespace std; \

  4. \

  5. class Person\

  6. {

    \

  7. public:\

  8. Person (int nAge) : m_nAge (nAge) {cout < < _T (” created an age of “) < < < < m_nAge _T (” “) < < endl; } \

  9. Person(Person& Somebody):m_nAge(Somebody. M_nAge + 10) {cout << _T(” copy creates an age of “) << _T(” Person “) << endl; } \

  10. ~ Person () {cout < < _T (” destructor an age of “) < < < < m_nAge _T (” “) < < endl; } \

  11. \

  12. private:\

  13.     int m_nAge;

  14. }; \

  15. \

  16. void Test(Person Somebody)\

  17. {

    \

  18. return; \

  19. } \

  20. \

  21. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])\

  22. {

    \

  23. Person Mike(20); \

  24. Test(Mike); \

  25. return 1; \

  26. }

The result of the above code is as follows:

Here is a brief explanation of the above code:

Person Mike(20);

You create a person whose age is 20

Test(Mike); Mike is passed as an argument to the Test function, and the Person Somebody copy constructor is called.

When the Test function returns, the life of the Somebody object ends and its destructor is called.

When _tmain returns, Mike’s declaration cycle ends and its destructor is called.

\

One key aspect of the above code is that the Test call involves copying the Mike object to the Somebody object.

\

  1. #include \

  2. #include \

  3. using namespace std; \

  4. \

  5. class Person\

  6. {

    \

  7. public:\

  8. Person (int nAge) : m_nAge (nAge) {cout < < _T (” created an age of “) < < < < m_nAge _T (” “) < < endl; } \

  9. Person(Person& Somebody):m_nAge(Somebody. M_nAge + 10) {cout << _T(” copy creates an age of “) << _T(” Person “) << endl; } \

  10. ~ Person () {cout < < _T (” destructor an age of “) < < < < m_nAge _T (” “) < < endl; } \

  11. \

  12. public:\

  13. int m_nAge; \

  14. \

  15. }; \

  16. \

  17. void Test(Person Somebody)\

  18. {

    \

  19. return; \

  20. } \

  21. \

  22. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])\

  23. {

    \

  24. Person Mike(20); \

  25. Test(Person(50)); \

  26. return 1; \

  27. }

The result of the above code is as follows:

As you can see from the result, no copy constructor is called this time, and the Person(50) temporary construct is Somebody, which is actually an object on the stack of Test, Whether this is the standard of C++ itself or the result of VS2008 helping us optimize it has not been studied yet.

\

The return value of a function is an object.

  1. #include \

  2. #include \

  3. using namespace std; \

  4. \

  5. class Person\

  6. {

    \

  7. public:\

  8. Person (int nAge) : m_nAge (nAge) {cout < < _T (” created an age of “) < < < < m_nAge _T (” “) < < endl; } \

  9. Person(Person& Somebody):m_nAge(Somebody. M_nAge + 10) {cout << _T(” copy creates an age of “) << _T(” Person “) << endl; } \

  10. ~ Person () {cout < < _T (” destructor an age of “) < < < < m_nAge _T (” “) < < endl; } \

  11. \

  12. public:\

  13. int m_nAge; \

  14. \

  15. }; \

  16. \

  17. Person Test()\

  18. {

    \

  19. Person Jack(30); \

  20. return Jack; \

  21. } \

  22. \

  23. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])\

  24. {

    \

  25. Person Tom = Test(); \

  26. return 1; \

  27. }

The result of the above code is as follows:

A brief explanation of the above code:

The Test function is executed, Person Jack(30) is executed, and the constructor is called.

Person Tom = Test(); After the Test function is executed, the Jack object is copied to Tom, so Tom’s copy constructor is executed. After the return value assignment is complete, the Jack object’s life cycle ends and the destructor is executed. After the _tmain function returns, the Tom object’s life cycle ends and the destructor is executed.

\

  1. #include \

  2. #include \

  3. using namespace std; \

  4. \

  5. class Person\

  6. {

    \

  7. public:\

  8. Person (int nAge) : m_nAge (nAge) {cout < < _T (” created an age of “) < < < < m_nAge _T (” “) < < endl; } \

  9. Person(Person& Somebody):m_nAge(Somebody. M_nAge + 10) {cout << _T(” copy creates an age of “) << _T(” Person “) << endl; } \

  10. ~ Person () {cout < < _T (” destructor an age of “) < < < < m_nAge _T (” “) < < endl; } \

  11. \

  12. public:\

  13. int m_nAge; \

  14. \

  15. }; \

  16. \

  17. Person Test()\

  18. {

    \

  19. Person Jack(30); \

  20. return Jack; \

  21. } \

  22. \

  23. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])\

  24. {

    \

  25. Test(); \

  26. cout << _T(“———————–“) << endl; \

  27. return 1; \

  28. }

The result of the above code is as follows:

Simply analyze the above code:

We see that the code does not define an object to accept the return value of Test, but the system still creates a temporary object to accept the return value of Test, but since this temporary object is not used, it is immediately destructed.

\

  1. #include \

  2. #include \

  3. using namespace std; \

  4. \

  5. class Person\

  6. {

    \

  7. public:\

  8. Person (int nAge) : m_nAge (nAge) {cout < < _T (” created an age of “) < < < < m_nAge _T (” “) < < endl; } \

  9. Person(Person& Somebody):m_nAge(Somebody. M_nAge + 10) {cout << _T(” copy creates an age of “) << _T(” Person “) << endl; } \

  10. ~ Person () {cout < < _T (” destructor an age of “) < < < < m_nAge _T (” “) < < endl; } \

  11. \

  12. public:\

  13. int m_nAge; \

  14. \

  15. }; \

  16. \

  17. Person Test()\

  18. {

    \

  19. return Person (30); \

  20. } \

  21. \

  22. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])\

  23. {

    \

  24. Person Tom = Test(); \

  25. cout << _T(“———————–“) << endl; \

  26. return 1; \

  27. }

The result of the above code is as follows:

As you can see from the result, there is no copy constructor called this time. The Person(30) temporarily constructed object is the Tom object. They are actually an object that exists on the stack of _tmain. It has not been studied.

\

3. The function passes in arguments and returns values as objects.

  1. #include \

  2. #include \

  3. using namespace std; \

  4. \

  5. class Person\

  6. {

    \

  7. public:\

  8. Person (int nAge) : m_nAge (nAge) {cout < < _T (” created an age of “) < < < < m_nAge _T (” “) < < endl; } \

  9. Person(Person& Somebody):m_nAge(Somebody. M_nAge + 10) {cout << _T(” copy creates an age of “) << _T(” Person “) << endl; } \

  10. ~ Person () {cout < < _T (” destructor an age of “) < < < < m_nAge _T (” “) < < endl; } \

  11. \

  12. public:\

  13. int m_nAge; \

  14. \

  15. }; \

  16. \

  17. Person Test(Person Somebody)\

  18. {

    \

  19. return Somebody; \

  20. } \

  21. \

  22. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])\

  23. {

    \

  24. Person Mike(20); \

  25. Person Tom = Test(Mike); \

  26. return 1; \

  27. }

The result of the above code is as follows:

A simple explanation of the above code is as follows:

Person Mike(20);

The constructor is executed

\

Pass Mike as an argument to the Test function, and copy the argument to the parameter calls Somebody’s copy constructor.

\

When the Test function is finished, the Somebody object is copied to the Tom object, and the copy constructor of the Tom object is called.

\

Somebody’s life cycle ends, and the destructor executes.

The life cycle of the Tom object ends, and the destructor is executed.

The Mike object’s life cycle ends, and the destructor is executed.

Firecat instance 1 (function argument is object)

#include “stdafx.h” #include

using namespace std; class Node { public: Node() { cout << “Node1()\n”; } // Use the default copy constructor int data1; int data2; }; void Fn(Node n) { cout << n.data1; cout << “,”; cout << n.data2; cout << “,”; n.data1 = 3; n.data2 = 3; } int _tmain(int argc, _TCHAR* argv[]) { Node n; n.data1 = 1; n.data2 = 1; Fn(n); cout << n.data1; cout << “,”; cout << n.data2; cout << endl; return 0; } \

Running results:

Node1() 1,1,1,1 press any key to continue.. \

#include “stdafx.h” #include

using namespace std; class Node { public: Node() { cout << “Node1()\n”; } // use the custom copy constructor Node(Node& n); int data1; int data2; }; Node::Node(Node &n) { cout << “Node2()\n”; } void Fn(Node n) { cout << n.data1; cout << “,”; cout << n.data2; cout << “,”; n.data1 = 3; n.data2 = 3; } int _tmain(int argc, _TCHAR* argv[]) { Node n; n.data1 = 1; n.data2 = 1; Fn(n); cout << n.data1; cout << “,”; cout << n.data2; cout << endl; return 0; } Run result:

Node1() Node2() 1245032,4266166,1,1 please press any key to continue.. \

Conclusion: When a class object is used as a function parameter, it is stored on the stack and does not affect the data of the argument. \

If the copy constructor is not overridden, the class’s other constructors will not be called. The data for the parameter is passed by memory copy. If overridden, the copy constructor will be called when the parameter is initialized, and no memory copy will be performed.

Firecat Instance 2 (function return value is object)

#include “stdafx.h”

#include

using namespace std; class Node { public: Node() { cout << “Node1()\n”; } // Use the default copy constructor int data1; }; Node Fn() { Node n; n.data1 = 1; return n; } int _tmain(int argc, _TCHAR* argv[]) { Node f = Fn(); cout << f.data1; cout << endl; return 0; } \

Running results:

Node1() 1 Press any key to continue..

\

#include “stdafx.h”

#include

using namespace std; class Node { public: Node() { cout << “Node1()\n”; } // Use the custom copy constructor Node(node&n) {cout << “Node2()\n”; } int data1; }; Node Fn() { Node n; n.data1 = 1; return n; } int _tmain(int argc, _TCHAR* argv[]) { Node f = Fn(); cout << f.data1; cout << endl; return 0; }

Running results:

Node1() Node2() -858993460 Press any key to continue..

\

———————

Reference article:

Notes for C++ haters 1 — data passing of class objects as function parameters \

C++ haters note 2 – the function returns the value of class object \