Раздел «Образование».FIVTLecturesTerm2Lecture04:
<<Лекции ФИВТ, 2-й семестр

Лекция 4. Основы ООП. Конструктор копирования. Класс String

Конструктор копирования

Есть несколько случаев, когда вызывается конструктор копирования:

class A {
public:
  // конструктор копирования
  A(const A &a) {
    cout << "copy" << endl;
  }
};
int main() {
  A a;
  A b(a); // явно вызывается конструктор копирования
}
class A {
public:
  // конструктор копирования
  A(const A &a) {
    cout << "copy" << endl;
  }
};
int main() {
  A a;
  A b = a; // явно вызывается конструктор копирования
 /*
  Вообще, конструкция
    ClassName x = y
  равносильна
    ClassName x(y);
 */
}
class A {
public:
  // конструктор копирования
  A(const A &a) {
    ...
  }
  ....
};

void do_smth(A x){
  ...
}

int main() {
  A a;
  do_smth(a); // вызывается конструктор копирования, чтобы
              // создать новый объект в стеке — локальную переменную
              // функции do_smth
}

Примеры

#include <iostream>
#include <string>
using namespace std;

class A {
public:
  A() { cout << "new A" << endl; };

  // конструктор копирования
  A(const A &a) {
    cout << "copy" << endl;
  }

  A& operator=(const A &a) {
    cout << "operator =" << endl;
    return *this;
  }
};
 
int
main() {
  A x, y;  // new A, new A
  y = x;   // operator =
  return 0;
}

int
main() {
  A x;     // new A
  A y = x; // copy, эквивалентно A y(x);
  A z;     // new A
  z = x;   // operator =
  A b(z);  // copy 
  return 0;
}

#include <iostream>
#include <string>
using namespace std;

class A {
public:
  A() { cout << "new A" << endl; };

  A(const A &a) {
    cout << "Copy" << endl;
  }

  A& operator=(const A &a) {
    cout << "operator =" << endl;
    return *this;
  }

  A operator+(const A &b) {
    return A();
  }
};
 

void 
print(const A &c) {
  cout << "Print" << endl;
}

int
main() {
  A x, y;
  y = x;
  print(x + y);
  return 0;
}

Вопросы:

Класс String

Задача: Написать класс String, позволяющий работать со строками как со скалярами (атомарными типами).

#include <cstring>

class String {
  char *str;
  unsigned allocated_size;
  unsigned size;
public:
  String() {
    allocated_size = 16;
    size = 0;
    str = new char[allocated_size];
    str[0] = 0;
  }

  String(const char *s) {
    size = strlen(s);
    str = new char[size + 1];
    strcpy(str, s);
    allocated_size = size + 1;
  }

  String(const String &s) {
    str = new char[ s.size + 1 ];
    strcpy(str, s.str);
    size = s.size;
    allocated_size = size + 1;
  }

  ~String() {
    delete[] str;
  }

  String& operator=(const String &s) {
    delete[] str;
    str = new char[ s.size + 1 ];
    strcpy(str, s.str);
    size = s.size;
    allocated_size = size + 1;
    return *this;
  }

  bool operator == (const String &s) const {
    return (strcmp(str, s.str) == 0);
  }

  String& operator +=(const String &s) {
    unsigned new_size = size + s.size;
    if (new_size >= allocated_size) {
      allocated_size = new_size * 2 + 1;
      char *new_str = new char[allocated_size];
      strcpy(new_str, str);
      delete[] str;
      str = new_str;
    }
    strcpy(str + size, s.str); 
    size = new_size; 
    return *this;
  }

  String operator + (const String &s) const {
    String new_s(*this);
    return new_s += s;
  }

  String& operator<<(const String &s) {
    return (*this += s);
  }
};

int 
main () {
  String c;
  String a = "asdasd";
  String b = "asda";
  //cout << a + b;
  //cout << a;
  a << "\n";
  a += "\n";
  String x = a;
  a << "dsfsf";
}

Вопросы:

  a << "\n";
Оператор '<<' определён для варианта, когда правый операнд есть объект класса String, а не char*, и по идее следовало бы писать так:
  a << String("\n");
Но первый вариант тоже "работает". Каким образом он работает?