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

Можете Вы помочь мне являетесь там определением в стандарте C++, который описывает, какой назовут конструктором или оператором присваивания в этом случае:

#include <iostream>

using namespace std;

class CTest
{
public:

 CTest() : m_nTest(0)
 {
  cout << "Default constructor" << endl;
 }

 CTest(int a) : m_nTest(a)
 {
  cout << "Int constructor" << endl;
 }

 CTest(const CTest& obj)
 {
  m_nTest = obj.m_nTest;
  cout << "Copy constructor" << endl;
 }

 CTest& operator=(int rhs)
 {
  m_nTest = rhs;
  cout << "Assignment" << endl;
  return *this;
 }

protected:
 int m_nTest;
};

int _tmain(int argc, _TCHAR* argv[])
{
 CTest b = 5;

 return 0;
}

Или это - просто вопрос компиляторной оптимизации?

5
задан Julian Popov 17 May 2010 в 09:21
поделиться

3 ответа

То, что здесь происходит, немного зависит от вашего компилятора. Он может создать временный объект, используя конструктор int, а затем скопировать конструкцию b из этого временного объекта. Однако, скорее всего, вызов конструктора копирования не будет выполняться. Ни в том, ни в другом случае не будет использоваться оператор присваивания.

7
ответ дан 18 December 2019 в 07:08
поделиться

В этом случае всегда вызывается конструктор по умолчанию, принимающий int . Это называется неявным преобразованием и семантически эквивалентно следующему коду:

CTest b(5);

Оператор присваивания никогда не вызывается при инициализации.Рассмотрим следующий случай:

CTest b = CTest(5);

Здесь мы вызываем конструктор (принимая int ) явно, а затем присваиваем результат b . Но опять же, никакой оператор присваивания никогда не вызывается. Строго говоря, в обоих случаях конструктор копирования вызывается после создания объекта типа CTest . Но на самом деле стандарт активно поощряет компиляторы оптимизировать здесь вызов конструктора копирования (§12.8 / 15) - на практике современные компиляторы C ++ не будут вызывать здесь вызов copycon.

11
ответ дан 18 December 2019 в 07:08
поделиться

CTest b = 5; является точным эквивалентом CTest b (CTest (5)); задействованы два конструктора: один принимает int (неявное преобразование из целое число 5) и конструктор копирования. Оператор присваивания здесь никоим образом не задействован.

Компилятор вполне может оптимизировать ненужную копию, поэтому результат будет таким, как если бы вы набрали CTest b (5) . Следовательно, во время выполнения оба вида вывода «Копировать конструктор» (GCC с параметром -fno-elide-constructors ) или нет (GCC по умолчанию) будут допустимыми выходными данными программы.

Однако концептуально компилятор должен проверять, существует ли доступный и подходящий конструктор копирования. Форма CTest b = 5; не будет скомпилирована, если а) конструктор копирования является закрытым / защищенным (недоступен) или б) конструктор копирования принимает аргумент по неконстантной ссылке (не может принять временный из CTest (5) - однако VC ++ может принять его как нестандартное расширение компилятора).

Боевой дух таков: нет простого способа определить, где и сколько раз в программе вызывается конструктор копирования, глядя на код. Копирование часто можно не выполнять, поэтому никогда не следует полагаться на побочные эффекты конструктора копирования. Если он делает то, что должен делать, то для вас не имеет значения, устраняет ли компилятор некоторые ненужные вызовы конструктора копирования.

4
ответ дан 18 December 2019 в 07:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: