order of constructors and destructors

2019-09-21 09:28发布

问题:

Here is a piece of code :

#include<iostream>
using namespace std;
class cls
{
    int x;
public:
        cls(int i=0) {cout<<" c1 "; x=i;}
        ~cls() {cout<<" d 1 ";}
};
class cls1
{
    int x; cls xx;
public:
        cls1(int i=0){cout<<" c2 ";x=i;}
        ~cls1(){cout<<" d2 ";}
}c;
class cls2
{
    int x;cls1 xx;cls xxx;
public:
    cls2(int i=0) {cout<<" c3 ";x=i;}
    ~cls2(){ cout<<" d3 ";}
};
int main()
{
    cls2 s;
    return 0;
}

The output is c1 c2 c1 c2 c1 c3 d3 d1 d2 d1 d2 d1 and I do not understand why . I would need some help.

回答1:

I would need some help.

It appears that one intent of the code is to obfuscate. Bad class names, misleading instance names, etc.

One idea to resist the obfuscation would be to find and practice with a coding standard.

The following code is the code above with simple substitutions from the coding standards I prefer.

Take a look at this and see if you can create questions about what you do not understand.

note - "d1" does not occur in your code but shows in your output. Thus, your output is not from the code you posted. I will assume it is the simple typo.


#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock  HRClk_t; // std-chrono-hi-res-clk
typedef HRClk_t::time_point                 Time_t;  // std-chrono-hi-res-clk-time-point
typedef std::chrono::microseconds           US_t;    // std-chrono-microseconds
using   namespace std::chrono_literals;          // support suffixes like 100ms, 2s, 30us
// examples:
//
//   Time_t start_us = HRClk_t::now();
//
//   auto  duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
//   auto     count_us = duration_us.count();
//   or
//   std::cout << "  complete " << duration_us.count() << " us" << std::endl;
#include <iostream>

// classes are types, so suffix with _t
// do not 'using namespace std;

class Foo_t  // was cls
{
   int x;

public:
   Foo_t(int i=0) {std::cout<<"  Foo_t: c1 \n";  x=i;}
   ~Foo_t()       {std::cout<<"  ~Foo_t: d1 \n";}      // typo fixed
};

class Bar_t  // was cls1
{
   int   x;
   Foo_t xx;

public:
   Bar_t(int i=0){std::cout<<"  Bar_t: c2 \n";  x=i;}
   ~Bar_t()      {std::cout<<"  ~Bar_t: d2 \n";}
}  bar;

class Zep_t // was cls2
{
   int     x;
   Bar_t  xx;
   Foo_t xxx;
public:
   Zep_t(int i=0) {std::cout<<"  Zep_t: c3 \n"; x=i;}
   ~Zep_t()       { std::cout<<"  ~Zep_t: d3 \n";}
};

class T490_t
{

public:

   T490_t() = default;
   ~T490_t() = default;

   int exec()
      {
         Zep_t z;
         return(0);
      }

}; // class T490_t


int main(int , char** )
{
   std::cout << "\n  main() start\n" << std::endl;

   Time_t start_us = HRClk_t::now();
   int retVal = -1;
   {
      T490_t   t490;
      retVal = t490.exec();
   }

   auto  duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
   std::cout << "\n  FINI   " << duration_us.count() << " us\n" << std::endl;
   return(retVal);
}

The output is:

  Foo_t: c1 
  Bar_t: c2 

  main() start

  Foo_t: c1 
  Bar_t: c2 
  Foo_t: c1 
  Zep_t: c3 
  ~Zep_t: d3 
  ~Foo_t: d1 
  ~Bar_t: d2 
  ~Foo_t: d1 

  FINI   33 us

  ~Bar_t: d2 
  ~Foo_t: d1 

Note how Foo_t and Bar_t are constructed prior to main().

Note how those 2 dtors run after main (after FINI).

Good luck.