2. C++ Avancé




2.2. Surcharge d'opérateur

La surcharge d'opérateur permet de redéfinir des opérateurs pour des classes créées par l'utilisateur afin de simplifier l'écriture du code.

Par exemple, dans le cas de matrices on peut redéfinir les opérateur +, * de manière à pouvoir écrire :

Matrix a(10,10), b(10,10), c(10,10), d(10,10);
d = a + b * c;

plutôt que d'écrire du code sous la forme :

Matrix a(10,10), b(10,10), c(10,10), d(10,10);
d.multiply(b, c);
d.add(a);

L'un des défauts de la surcharge d'opérateurs est le fait que l'on perd généralement en efficacité car les opérateurs masquent la création d'instances temporaires et l'utilisation du constructeur par recopie ou de l'opérateur d'affectation.

2.2.1. fonction amie ou opérateur

La surcharge d'opérateur peut être réalisée de deux façons différentes :

  • soit en surchargeant effectivement l'opérateur pour la classe donnée : a.+(b)
  • soit en créant une fonction amie : +(a,b)

2.2.1.a  Exemple matrices

On obtient le même comportement dans les deux cas.

  1. #include <vector>
  2. #include <iostream>
  3. #include <initializer_list>
  4. using namespace std;
  5.  
  6. /**
  7.  ************************************************
  8.  * Matrix of float, implementation with vector<>
  9.  ************************************************
  10.  */
  11. class Matrix {
  12.  
  13. // ==============================================
  14. // data members
  15. // ==============================================
  16. protected:
  17.     int n_row; // number of rows
  18.     int n_cols; // number of columns
  19.     typedef vector<float> RowType; // Type of a row
  20.     vector<RowType> rows;
  21.  
  22. public:
  23.     // counters
  24.     static int n_cons_calls, n_copy_calls, n_assign_calls, n_destr_calls;
  25.  
  26.  
  27. // ==============================================
  28. // methods
  29. // ==============================================
  30. public:
  31.     // ------------------------------------------
  32.     // constructor with number of rows and columns
  33.     // ------------------------------------------
  34.     Matrix(int r, int c) {
  35.         n_rows = r;
  36.         n_cols = c;
  37.         size = r * c;
  38.         for (int y = 0; y < n_rows; ++y) {
  39.             rows.push_back(RowType(n_cols));
  40.         }
  41.         ++n_cons_calls;
  42.     }
  43.    
  44.     // ------------------------------------------
  45.     // constructor with initializer list
  46.     // the first two values represent the number of rows and columns
  47.     // ------------------------------------------
  48.     Matrix(initializer_list<float> l) {
  49.         auto it = l.begin();
  50.         n_rows = static_cast<int>(*it++);
  51.         n_cols = static_cast<int>(*it++);
  52.         //cerr << n_rows << endl;
  53.         //cerr << n_cols << endl;
  54.         size = n_rows * n_cols;
  55.         for (int y = 0; y < n_rows; ++y) {
  56.             rows.push_back(RowType(n_cols));
  57.         }
  58.         for (int y = 0; y < n_rows; ++y) {
  59.             for (int x = 0; x < n_cols; ++x) {
  60.                 rows[y][x] = *it++;
  61.             }
  62.         }
  63.         ++n_cons_calls;
  64.     }
  65.    
  66.     // ------------------------------------------
  67.     // destructor
  68.     // ------------------------------------------
  69.     ~Matrix() {
  70.         rows.clear();
  71.         ++n_destr_calls;
  72.     }
  73.    
  74.     // ------------------------------------------
  75.     // copy constructor
  76.     // ------------------------------------------
  77.     Matrix(const Matrix& m) {
  78.         n_cols = m.n_cols;
  79.         size = n_rows * n_cols;
  80.         for (int y = 0; y < n_rows; ++y) {
  81.             rows.push_back(m.rows[y]);
  82.         }
  83.         ++n_copy_calls;
  84.     }
  85.    
  86.     // ------------------------------------------
  87.     // assignment operator
  88.     // ------------------------------------------
  89.     Matrix& operator=(const Matrix& m) {
  90.         if (&m != this) {
  91.             rows.clear();
  92.             n_rows = m.n_rows;
  93.             n_cols = m.n_cols;
  94.             size = n_rows * n_cols;
  95.             for (int y = 0; y < n_rows; ++y) {
  96.                 rows.push_back(m.rows[y]);
  97.             }
  98.         }
  99.         ++n_assign_calls;
  100.         return *this;
  101.     }
  102.    
  103.     // ------------------------------------------
  104.     // subscript operator definition to access row
  105.     // ------------------------------------------
  106.     RowType& operator[](int y) {
  107.         return rows[y];
  108.     }
  109.    
  110.     // ------------------------------------------
  111.     // set element
  112.     // ------------------------------------------
  113.     void set(int y, int x, float v) {
  114.         rows[y][x] = v;
  115.     }
  116.    
  117.     // ------------------------------------------
  118.     // get element
  119.     // ------------------------------------------
  120.     float get(int y, int x) {
  121.         return rows[y][x];
  122.     }
  123.    
  124.     // ------------------------------------------
  125.     // addition operator
  126.     // ------------------------------------------
  127.     Matrix operator+(const Matrix& b) {
  128.         Matrix m(n_rows, n_cols);
  129.         for (int y = 0; y < n_rows; ++y) {
  130.             for (int x = 0; x < n_cols; ++x) {
  131.                 m.rows[y][x] = rows[y][x] + b.rows[y][x];
  132.             }
  133.         }
  134.         return m;
  135.     }
  136.    
  137.     // ------------------------------------------
  138.     // multiplication operator
  139.     // ------------------------------------------
  140.     Matrix operator*(const Matrix& b) {
  141.         Matrix m(n_rows, b.n_cols);
  142.         for (int y = 0; y < n_rows; ++y) {
  143.             for (int x = 0; x < b.n_cols; ++x) {
  144.                 float sum = 0.0;
  145.                 for (int k = 0; k < n_cols; ++ k) {
  146.                     sum += rows[y][k] * b.rows[k][x];
  147.                 }  
  148.                 m.rows[y][x] = sum;
  149.             }
  150.         }
  151.         return m;
  152.     }
  153.    
  154.     // ------------------------------------------
  155.     // print
  156.     // ------------------------------------------
  157.     ostream& print(ostream& out) {
  158.         for (int y = 0; y < n_rows; ++y) {
  159.             for (int x = 0; x < n_cols; ++x) {
  160.                 out.width(7);
  161.                 out << rows[y][x] << " ";
  162.             }
  163.             out << endl;
  164.         }
  165.         return out;
  166.     }
  167.    
  168.     friend ostream& operator<<(ostream& out, Matrix& m) {
  169.         return m.print(out);
  170.     }
  171. };
  172.  
  173. int Matrix::n_cons_calls = 0;
  174. int Matrix::n_copy_calls = 0;
  175. int Matrix::n_assign_calls = 0;
  176. int Matrix::n_destr_calls = 0;
  177.  
  178.  
  179. int main() {
  180.     // create matrices
  181.     Matrix a({ 3, 3, 1, 2, 3, 4, 2, 0, -5, 0, -1});
  182.     Matrix b({ 3, 3, 8, 2, -1, 7, 3, -4, -2, 0, 3});
  183.     Matrix c({ 2, 3, 1, 0, -1, -2, 1, 0});
  184.     Matrix d({ 2, 2, 0.5, -0.4, 0.2, -0.3});
  185.     Matrix e(2,2);
  186.    
  187.     // modify one element
  188.     a[2][2] = 99;
  189.    
  190.     // perform calculation
  191.     e = d * c * (a + b);
  192.    
  193.     cout << e << endl;
  194.    
  195.     cerr << "a, b and c will not be modified" << endl;
  196.     cerr << "     constructor calls = " << Matrix::n_cons_calls << endl;
  197.     cerr << "      destructor calls = " << Matrix::n_destr_calls << endl;
  198.     cerr << "copy constructor calls = " << Matrix::n_copy_calls << endl;
  199.     cerr << "      assignment calls = " << Matrix::n_assign_calls << endl;
  200.     cerr << a << endl;
  201.     cerr << b << endl;
  202.     cerr << c << endl;
  203.     cerr << d << endl;
  204. }
  205.  
  1. #include <vector>
  2. #include <iostream>
  3. #include <initializer_list>
  4. using namespace std;
  5.  
  6. /**
  7.  ************************************************
  8.  * Matrix of float, implementation with vector<>
  9.  ************************************************
  10.  */
  11. class Matrix {
  12.  
  13. // ==============================================
  14. // data members
  15. // ==============================================
  16. protected:
  17.     int n_rows; // number of rows
  18.     int n_cols; // number of columns
  19.     typedef vector<float> RowType; // Type of a row
  20.     vector<RowType> rows;
  21.  
  22. public:
  23.     // counters
  24.     static int n_cons_calls, n_copy_calls, n_assign_calls,
  25.         n_destr_calls;
  26.    
  27. // ==============================================
  28. // methods
  29. // ==============================================
  30. public:
  31.     // ------------------------------------------
  32.     // constructor with number of rows and columns
  33.     // ------------------------------------------
  34.     Matrix(int r, int c) {
  35.         n_rows = r;
  36.         n_cols = c;
  37.         for (int y = 0; y < n_rows; ++y) {
  38.             rows.push_back(RowType(n_cols));
  39.         }
  40.         ++n_cons_calls;
  41.     }
  42.    
  43.     // ------------------------------------------
  44.     // constructor with initializer list
  45.     // the first two values represent the number of rows and columns
  46.     // ------------------------------------------
  47.     Matrix(initializer_list<float> l) {
  48.         auto it = l.begin();
  49.         n_rows = static_cast<int>(*it++);
  50.         n_cols = static_cast<int>(*it++);
  51.         //cerr << n_rows << endl;
  52.         //cerr << n_cols << endl;
  53.         for (int y = 0; y < n_rows; ++y) {
  54.             rows.push_back(RowType(n_cols));
  55.         }
  56.         for (int y = 0; y < n_rows; ++y) {
  57.             for (int x = 0; x < n_cols; ++x) {
  58.                 rows[y][x] = *it++;
  59.             }
  60.         }
  61.         ++n_cons_calls;
  62.     }
  63.    
  64.     // ------------------------------------------
  65.     // destructor
  66.     // ------------------------------------------
  67.     ~Matrix() {
  68.         rows.clear();
  69.         ++n_destr_calls;
  70.     }
  71.    
  72.     // ------------------------------------------
  73.     // copy constructor
  74.     // ------------------------------------------
  75.     Matrix(const Matrix& m) {
  76.         n_cols = m.n_cols;
  77.         for (int y = 0; y < n_rows; ++y) {
  78.             rows.push_back(m.rows[y]);
  79.         }
  80.         ++n_copy_calls;
  81.     }
  82.    
  83.     // ------------------------------------------
  84.     // assignment operator
  85.     // ------------------------------------------
  86.     Matrix& operator=(const Matrix& m) {
  87.         if (&m != this) {
  88.             rows.clear();
  89.             n_rows = m.n_rows;
  90.             n_cols = m.n_cols;
  91.             for (int y = 0; y < n_rows; ++y) {
  92.                 rows.push_back(m.rows[y]);
  93.             }
  94.         }
  95.         ++n_assign_calls;
  96.         return *this;
  97.     }
  98.    
  99.     // ------------------------------------------
  100.     // subscript operator definition to access row
  101.     // ------------------------------------------
  102.     RowType& operator[](int y) {
  103.         return rows[y];
  104.     }
  105.    
  106.     // ------------------------------------------
  107.     // set or get element using operator ()
  108.     // ------------------------------------------
  109.     float& operator()(int y, int x) {
  110.         return rows[y][x];
  111.     }
  112.    
  113.     // ------------------------------------------
  114.     // set element
  115.     // ------------------------------------------
  116.     void set(int y, int x, float v) {
  117.         rows[y][x] = v;
  118.     }
  119.    
  120.     // ------------------------------------------
  121.     // gete element
  122.     // ------------------------------------------
  123.     float get(int y, int x) {
  124.         return rows[y][x];
  125.     }
  126.    
  127.     // ------------------------------------------
  128.     // addition operator as friend
  129.     // ------------------------------------------
  130.     friend Matrix operator+(const Matrix& a, const Matrix& b) {
  131.         Matrix m(a.n_rows, a.n_cols);
  132.         for (int y = 0; y < a.n_rows; ++y) {
  133.             for (int x = 0; x < a.n_cols; ++x) {
  134.                 m.rows[y][x] = a.rows[y][x] + b.rows[y][x];
  135.             }
  136.         }
  137.         return m;
  138.     }
  139.    
  140.     // ------------------------------------------
  141.     // multiplication operator as friend
  142.     // ------------------------------------------
  143.     friend Matrix operator*(const Matrix& a, const Matrix& b) {
  144.         Matrix m(a.n_rows, b.n_cols);
  145.         for (int y = 0; y < a.n_rows; ++y) {
  146.             for (int x = 0; x < b.n_cols; ++x) {
  147.                 float sum = 0.0;
  148.                 for (int k = 0; k < a.n_cols; ++ k) {
  149.                     sum += a.rows[y][k] * b.rows[k][x];
  150.                 }  
  151.                 m.rows[y][x] = sum;
  152.             }
  153.         }
  154.         return m;
  155.     }
  156.    
  157.     // ------------------------------------------
  158.     // print
  159.     // ------------------------------------------
  160.     ostream& print(ostream& out) {
  161.         for (int y = 0; y < n_rows; ++y) {
  162.             for (int x = 0; x < n_cols; ++x) {
  163.                 out.width(7);
  164.                 out << rows[y][x] << " ";
  165.             }
  166.             out << endl;
  167.         }
  168.         return out;
  169.     }
  170.    
  171.     friend ostream& operator<<(ostream& out, Matrix& m) {
  172.         return m.print(out);
  173.     }
  174. };
  175.  
  176. int Matrix::n_cons_calls = 0;
  177. int Matrix::n_copy_calls = 0;
  178. int Matrix::n_assign_calls = 0;
  179. int Matrix::n_destr_calls = 0;
  180.  
  181. int main() {
  182.     // creates matrices
  183.     Matrix a({ 3, 3, 1, 2, 3, 4, 2, 0, -5, 0, -1});
  184.     Matrix b({ 3, 3, 8, 2, -1, 7, 3, -4, -2, 0, 3});
  185.     Matrix c({ 2, 3, 1, 0, -1, -2, 1, 0});
  186.     Matrix d({ 2, 2, 0.5, -0.4, 0.2, -0.3});
  187.     Matrix e(2,2);
  188.  
  189.     // modify element  
  190.     a[2][2] = 99;
  191.     // or
  192.     a(2,2) = 99;
  193.    
  194.     // perform calculation
  195.     e = d * c * (a + b);
  196.     cout << e << endl;
  197.    
  198.     cerr << "a, b and c will not be modified" << endl;
  199.     cerr << "     constructor calls = " << Matrix::n_cons_calls << endl;
  200.     cerr << "      destructor calls = " << Matrix::n_destr_calls << endl;
  201.     cerr << "copy constructor calls = " << Matrix::n_copy_calls << endl;
  202.     cerr << "      assignment calls = " << Matrix::n_assign_calls << endl;
  203.     cerr << a << endl;
  204.     cerr << b << endl;
  205.     cerr << c << endl;
  206.     cerr << d << endl;
  207. }
  208.  
   10.8     3.2   -46.8 
    5.3     1.7   -17.6 

a, b and c will not be modified
     constructor calls = 8
      destructor calls = 3
copy constructor calls = 0
      assignment calls = 1
      1       2       3 
      4       2       0 
     -5       0      99 

      8       2      -1 
      7       3      -4 
     -2       0       3 

      1       0      -1 
     -2       1       0 

    0.5    -0.4 
    0.2    -0.3 

2.2.1.b  Exemple vecteurs

dans ce premier exemple Vector& operator+(const Vector& a), v1 sera modifié mais le nombre d'appels aux méthodes est minimum.

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4.  
  5. /**
  6.  * Vector of integers
  7.  */
  8. class Vector {
  9. // ==============================================
  10. // data members
  11. // ==============================================
  12. protected:
  13.     int size;
  14.     int *elements;
  15. public:
  16.     static int count_cons, count_destr, count_copy, count_assign;
  17.    
  18. // ==============================================
  19. // methods
  20. // ==============================================  
  21. public:
  22.     /**
  23.      * constructor
  24.      * @param sz maximum number of elements
  25.      */
  26.     Vector(int sz = 10) {
  27.         size = sz;
  28.         elements = new int [ size ];
  29.         ++count_cons;
  30.     }
  31.    
  32.     /**
  33.      * destructor
  34.      */
  35.     ~Vector() {
  36.         delete [] elements;
  37.         ++count_destr;
  38.     }
  39.    
  40.     /**
  41.      * copy constructor
  42.      * @param v existing Vector used for initialization
  43.      */
  44.     Vector(Vector& v) {
  45.         size = v.size;
  46.         elements = new int [ size ];
  47.         memcpy(elements, v.elements, sizeof(int)*size);
  48.         ++count_copy;
  49.     }
  50.    
  51.     /**
  52.      * assignment operator
  53.      * @param v existing Vector to assign
  54.      */
  55.     Vector& operator=(const Vector& v) {
  56.         if (&v != this) {
  57.             delete [] elements;
  58.             size = v.size;
  59.             elements = new int [ size ];
  60.             memcpy(elements, v.elements, sizeof(int)*size);
  61.         }
  62.         ++count_assign;
  63.         return *this;
  64.     }
  65.    
  66.     /**
  67.      * fill vector with value
  68.      * @param n value used to fill the Vector
  69.      */
  70.     void fill(int n) {
  71.         for (int i=0; i<size; ++i) {
  72.             elements[i] = n;
  73.         }
  74.     }
  75.    
  76.     /**
  77.      * print Vector
  78.      * @param out output stream
  79.      */
  80.     ostream& print(ostream& out) {
  81.         for (int i=0; i<size; ++i) {
  82.             out << elements[i] << " ";
  83.         }
  84.         return out;
  85.     }
  86.    
  87.     friend ostream& operator<<(ostream& out, Vector& v) {
  88.         return v.print(out);
  89.     }
  90.    
  91.     /**
  92.      * addition of two vectors
  93.      * operator overloading: this Vector is modified and will contain
  94.      * (*this+a)
  95.      * @param a Vector to add
  96.      */
  97.     Vector& operator+(const Vector& a) {
  98.         for (int i=0; i<size; ++i) {
  99.             elements[i] += a.elements[i];
  100.         }
  101.         return *this;
  102.     }
  103. };
  104.  
  105. int Vector::count_cons = 0;
  106. int Vector::count_destr = 0;
  107. int Vector::count_copy = 0;
  108. int Vector::count_assign = 0;
  109.  
  110. int main() {
  111.    
  112.     Vector v3;
  113.     for (int i=0; i<1000; ++i) {
  114.         Vector v1;
  115.         Vector v2;
  116.         v1.fill(1);
  117.         v2.fill(2);
  118.         v3 = v1 + v2;
  119.         if (i == 0) {
  120.             cout << "v1 = " << v1 << endl;
  121.             cout << "v2 = " << v2 << endl;
  122.             cout << "v3 = " << v3 << endl;
  123.         }
  124.     }
  125.    
  126.     cout << "cons   = " << Vector::count_cons << endl;
  127.     cout << "destr  = " << Vector::count_destr << endl;
  128.     cout << "copy   = " << Vector::count_copy << endl;
  129.     cout << "assign = " << Vector::count_assign << endl;
  130.     int total = Vector::count_cons + Vector::count_destr + Vector::count_copy + Vector::count_assign;
  131.     cout << "====================" << endl;
  132.     cout << "total  = " << total << endl;
  133.     return 0;
  134. }
  135.  
  136.  
v1 = 3 3 3 3 3 3 3 3 3 3 
v2 = 2 2 2 2 2 2 2 2 2 2 
v3 = 3 3 3 3 3 3 3 3 3 3 
cons   = 2001
destr  = 2000
copy   = 0
assign = 1000
====================
total  = 5001

dans ce deuxième exemple Vector operator+(const Vector& a), v1 ne sera pas modifié mais le nombre d'appels aux méthodes est plus important car on doit créer un vecteur temporaire pour l'opérateur +.

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4.  
  5. class Vector {
  6. protected:
  7.     int size;
  8.     int *elements;
  9. public:
  10.     static int count_cons, count_destr, count_copy, count_assign;
  11.    
  12. public:
  13.     // constructor
  14.     Vector(int sz = 10) {
  15.         size = sz;
  16.         elements = new int [ size ];
  17.         ++count_cons;
  18.     }
  19.    
  20.     // destructor
  21.     ~Vector() {
  22.         delete [] elements;
  23.         ++count_destr;
  24.     }
  25.    
  26.     // copy constructor
  27.     Vector(Vector& v) {
  28.         size = v.size;
  29.         elements = new int [ size ];
  30.         memcpy(elements, v.elements, sizeof(int)*size);
  31.         ++count_copy;
  32.     }
  33.    
  34.     // assignment operator
  35.     Vector& operator=(const Vector& v) {
  36.         if (&v != this) {
  37.             delete [] elements;
  38.             size = v.size;
  39.             elements = new int [ size ];
  40.             memcpy(elements, v.elements, sizeof(int)*size);
  41.         }
  42.         ++count_assign;
  43.         return *this;
  44.     }
  45.    
  46.     // fill vector with value
  47.     void fill(int n) {
  48.         for (int i=0; i<size; ++i) {
  49.             elements[i] = n;
  50.         }
  51.     }
  52.    
  53.     ostream& print(ostream& out) {
  54.         for (int i=0; i<size; ++i) {
  55.             out << elements[i] << " ";
  56.         }
  57.         return out;
  58.     }
  59.    
  60.     friend ostream& operator<<(ostream& out, Vector& v) {
  61.         return v.print(out);
  62.     }
  63.    
  64.     // addition of two vectors: operator overloading
  65.     // v1 is not modified but we need to create a temporary
  66.     // variable tmp
  67.     Vector operator+(const Vector& a) {
  68.         Vector tmp(size);
  69.         for (int i=0; i<size; ++i) {
  70.             tmp.elements[i] = elements[i] + a.elements[i];
  71.         }
  72.         return tmp;
  73.     }
  74. };
  75.  
  76. int Vector::count_cons = 0;
  77. int Vector::count_destr = 0;
  78. int Vector::count_copy = 0;
  79. int Vector::count_assign = 0;
  80.  
  81. int main() {
  82.    
  83.     Vector v3;
  84.     for (int i=0; i<1000; ++i) {
  85.         Vector v1;
  86.         Vector v2;
  87.         v1.fill(1);
  88.         v2.fill(2);
  89.         v3 = v1 + v2;
  90.         if (i == 0) {
  91.             cout << "v1 = " << v1 << endl;
  92.             cout << "v2 = " << v2 << endl;
  93.             cout << "v3 = " << v3 << endl;
  94.         }
  95.     }
  96.    
  97.     cout << "cons   = " << Vector::count_cons << endl;
  98.     cout << "destr  = " << Vector::count_destr << endl;
  99.     cout << "copy   = " << Vector::count_copy << endl;
  100.     cout << "assign = " << Vector::count_assign << endl;
  101.     int total = Vector::count_cons + Vector::count_destr + Vector::count_copy + Vector::count_assign;
  102.     cout << "====================" << endl;
  103.     cout << "total  = " << total << endl;
  104.     return 0;
  105. }
  106.  
  107.  
v1 = 1 1 1 1 1 1 1 1 1 1 
v2 = 2 2 2 2 2 2 2 2 2 2 
v3 = 3 3 3 3 3 3 3 3 3 3 
cons   = 3001
destr  = 3000
copy   = 0
assign = 1000
====================
total  = 7001

dans ce troisième exemple friend Vector operator+(const Vector& a, const Vector& b), v1 ne sera pas modifié mais le nombre d'appels aux méthodes est plus important car on doit créer un vecteur temporaire dans la fonction amie +.

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4.  
  5. class Vector {
  6. protected:
  7.     int size;
  8.     int *elements;
  9. public:
  10.     static int count_cons, count_destr, count_copy, count_assign;
  11.    
  12. public:
  13.     // constructor
  14.     Vector(int sz = 10) {
  15.         size = sz;
  16.         elements = new int [ size ];
  17.         ++count_cons;
  18.     }
  19.    
  20.     // destructor
  21.     ~Vector() {
  22.         delete [] elements;
  23.         ++count_destr;
  24.     }
  25.    
  26.     // copy constructor
  27.     Vector(Vector& v) {
  28.         size = v.size;
  29.         elements = new int [ size ];
  30.         memcpy(elements, v.elements, sizeof(int)*size);
  31.         ++count_copy;
  32.     }
  33.    
  34.     // assignment operator
  35.     Vector& operator=(const Vector& v) {
  36.         if (&v != this) {
  37.             delete [] elements;
  38.             size = v.size;
  39.             elements = new int [ size ];
  40.             memcpy(elements, v.elements, sizeof(int)*size);
  41.         }
  42.         ++count_assign;
  43.         return *this;
  44.     }
  45.    
  46.     void fill(int n) {
  47.         for (int i=0; i<size; ++i) {
  48.             elements[i] = n;
  49.         }
  50.     }
  51.    
  52.     ostream& print(ostream& out) {
  53.         for (int i=0; i<size; ++i) {
  54.             out << elements[i] << " ";
  55.         }
  56.         return out;
  57.     }
  58.    
  59.     friend ostream& operator<<(ostream& out, Vector& v) {
  60.         return v.print(out);
  61.     }
  62.    
  63.     // addition of two vectors: friend function
  64.     // v1 is not modified but we need to create a temporary
  65.     // variable tmp
  66.     friend Vector operator+(const Vector& a, const Vector& b) {
  67.         Vector tmp(a.size);
  68.         for (int i=0; i<a.size; ++i) {
  69.             tmp.elements[i] += a.elements[i] + b.elements[i];
  70.         }
  71.         return tmp;
  72.     }
  73. };
  74.  
  75. int Vector::count_cons = 0;
  76. int Vector::count_destr = 0;
  77. int Vector::count_copy = 0;
  78. int Vector::count_assign = 0;
  79.  
  80. int main() {
  81.    
  82.     Vector v3;
  83.     for (int i=0; i<1000; ++i) {
  84.         Vector v1;
  85.         Vector v2;
  86.         v1.fill(1);
  87.         v2.fill(2);
  88.         v3 = v1 + v2;
  89.         if (i == 0) {
  90.             cout << "v1 = " << v1 << endl;
  91.             cout << "v2 = " << v2 << endl;
  92.             cout << "v3 = " << v3 << endl;
  93.         }
  94.     }
  95.    
  96.     cout << "cons   = " << Vector::count_cons << endl;
  97.     cout << "destr  = " << Vector::count_destr << endl;
  98.     cout << "copy   = " << Vector::count_copy << endl;
  99.     cout << "assign = " << Vector::count_assign << endl;
  100.     int total = Vector::count_cons + Vector::count_destr + Vector::count_copy + Vector::count_assign;
  101.     cout << "====================" << endl;
  102.     cout << "total  = " << total << endl;
  103.     return 0;
  104. }
  105.  
  106.  
v1 = 1 1 1 1 1 1 1 1 1 1 
v2 = 2 2 2 2 2 2 2 2 2 2 
v3 = 3 3 3 3 3 3 3 3 3 3 
cons   = 3001
destr  = 3000
copy   = 0
assign = 1000
====================
total  = 7001