4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
1

Вызов конструктора копий

29.10.2014, 06:27. Показов 1440. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всех приветствую!

Имеется следующий простенький код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
 
using namespace std;
 
class Object
{
private:
  int itsVal;
public:
  Object() {cout << "Standart constructor called..." << "\n";}
  Object(int val) {cout << "User constructor called..." << "\n"; itsVal=val;}
  Object(const Object &rhs) {cout << "Copy constructor called..." << "\n"; itsVal=rhs.GetVal();};
  ~Object() {cout << "Destructor called..." << "\n";}
  int GetVal() const {return itsVal;}
  Object Func() {return *this;}
};
 
int main()
{
  Object NewObject (100);
  Object NewObject2=NewObject.Func();
  return 0;
}
Результат его выполнения:

User constructor called...
Copy constructor called...
Destructor called...
Destructor called...

Вопрос:
Почему конструктор копий вызывается только один раз? Ведь, по идее, в строке 21 он должен вызываться два раза: один раз при возврате значения из функции "Func", второй - при вызове оператора присвоения, ведь я инициализирую значение второго объекта непосредственно при его объявлении.

Добавлено через 21 минуту
Да и деструктор, кстати, должен быть вызван 3 раза - для двух объектов("NewObject" и "NewObject2") и для копии объекта "NewObject", созданной при возврате значения из функции "Func". Или я чего-то недопонимаю?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.10.2014, 06:27
Ответы с готовыми решениями:

Вызов конструктора копий
Почему из строк 186-191 вызывается конструктор копий 83-91? #include &quot;stdafx.h&quot; #define DEBUG...

Не хватает одного конструктора копий
Вообщем поставил в коде вывод сообщений через cout, чтобы проследить кто и в какой момент...

Ключевое слово const в параметрах конструктора копий
вот такая делема возникла))есть билдер 2006 и 2009 в 6-ом конструктор копий определен так...

Вызов конструктора
void main() { std::string stemporary; int itemporary; float ftemporary; float fftemporary;...

5
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2014, 06:31 2
Цитата Сообщение от Alexey104 Посмотреть сообщение
Почему конструктор копий вызывается только один раз? Ведь, по идее, в строке 21 он должен вызываться два раза:
От реализации зависит, временный объект (при возврате) может не создаваться.
1
Вездепух
Эксперт CЭксперт С++
11689 / 6368 / 1723
Регистрация: 18.10.2014
Сообщений: 16,051
29.10.2014, 06:37 3
Во-первых, никакого "оператора присвоения" в вашем коде нет. Вот это '=' в синтаксисе инициализации - это просто символ '=', часть синтаксиса инициализации, а никакой не "оператор присвоения".

Во-вторых, вы правы: с точки зрения формально-абстрактного С++ конструктор копирования тут должен вызваться два раза: первый раз когда внутри функции 'Func()' значение '*this' копируется в безымянный временный объект, и второй раз когда этот безымянный временный объект копируется в 'NewObject2'

Однако спецификация языка С++ разрешает компиляторам устранять этот промежуточный временный объект в целях оптимизации кода и исключать "лишний" вызов конструктора копирования. Стандарт языка разрешает исключать вызов конструктора копирования даже если конструктор копирования содержит наблюдаемое поведение. Именно это и произошло в вашем случае. Т.е. при выполнении 'return *this' внутри 'Func()' компилятор напрямую копирует '*this' в 'NewObject2' одним-единственным вызовом конструктора копирования.

Если добавить в код печать значений указателей 'this', то сразу станет видно что куда копируется.

Похожее явление будет иметь место если вы напишете вот такую инициализацию

C++
1
Object obj = 5;
Формально компилятор обязан вызвать два конструктора, как будто вы написали

C++
1
Object obj = Object(5);
Но фактически компилятор имеет право устранить промежуточный временный объект и обойтись только одним вызовом конструктора, как будто вы написали

C++
1
Object obj(5);
1
4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
29.10.2014, 06:47  [ТС] 4
Спасибо, понятно.

Хотелось бы ещё уточнить отличия оператора присвоения от простого символа '='. Если бы при реализации класса я написал что-нибудь типа этого:
C++
1
2
3
4
5
6
void operator =(const Object &);
 
void Object::operator =(const Object &rhs)
{
   itsVal = rhs.GetVal();
}
, то в таком случае символ '=' для объекта класса стал бы оператором присвоения?
0
Вездепух
Эксперт CЭксперт С++
11689 / 6368 / 1723
Регистрация: 18.10.2014
Сообщений: 16,051
29.10.2014, 06:56 5
Цитата Сообщение от Alexey104 Посмотреть сообщение
то в таком случае символ '=' для объекта класса стал бы оператором присвоения?
Оператор присваивания вы имеет полное право переопределить. Но все равно в контексте объявления с инициализацией

C++
1
Object obj = Object(5);
этот оператор никогда вызываться не будет.

Инициализация - это инициализация. Присваивание - это присваивание. Это совсем разные вещи. Чтобы отличить инициализацию от присваивания надо смотреть отнюдь не на символ '='.

Ваш оператор присваивания будет вызываться вот в таком случае

C++
1
2
Object obj;
obj = Object(5);
Вот это действительно присваивание. А предыдущий пример - это не присваивание вообще.
1
4 / 4 / 0
Регистрация: 26.10.2014
Сообщений: 105
29.10.2014, 07:10  [ТС] 6
Всё понял, благодарю за ликбез, буду дальше учиться...
0
29.10.2014, 07:10
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.10.2014, 07:10
Помогаю со студенческими работами здесь

вызов конструктора
Здарова! Есть допустим класс: class Str { Str(); Str(Str&amp;); Str(char*); };

вызов конструктора
Почему при повторном вызове конструктора выбивает ошибку ?Вот здесь ObjX(INUSE); no match for...

Неоднозначный вызов конструктора
class Verylong{ public: Verylong (long x = 0) { enter(x);} Verylong (const...

Вызов копирующего конструктора
Помогите привести примеры для всех случаев.. Копирующий конструктор вызывается в следующих...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru