Подтвердить что ты не робот

Почему компилятор меня прослушивает на этом?

(с использованием Visual С++ 2010, компиляция при отладке с отключенными оптимизациями)

У меня есть следующий очень простой класс:

class exampleClass
{
public:
    exampleClass()
    {
        cout << "in the default ctor" << endl;
    }
private:
    exampleClass (const exampleClass& e)
    {
        cout << "in the copy ctor" << endl;
    }
};

Когда я пытаюсь скомпилировать его со следующим основным:

#include <iostream>
using namespace std;

int main()
{
    exampleClass e1=exampleClass();
    return 0;
}

Я получаю ошибку компиляции:

'exampleClass::exampleClass' : cannot access private
                               member declared in class 'exampleClass'

Когда я удаляю модификатор доступа "private" из копии ctor, программа компилирует и печатает только:

in the default ctor

Почему это происходит? Если компилятор не будет ссылаться на копию ctor в любом случае, почему это меня прослушивает?

Так как некоторые люди пропустили первую строку (по крайней мере, до некоторых изменений), я повторю ее:

Я скомпилирован в отладке с отключенными оптимизациями.

4b9b3361

Ответ 1

Этот тип инициализации называется копированием-инициализацией. Я считаю, что здесь применяется следующее предложение из стандарта С++ 11 (пункт 8.5.16, стр. 204):

Если инициализация является прямой инициализацией или если она copy-initialization, где cv-неквалифицированная версия источника type - это тот же класс, что и производный класс класса назначения, конструкторы. Соответствующие конструкторы перечислены (13.3.1.3), а лучший выбирается путем перегрузки резолюции (13.3). Выбранный таким образом конструктор вызывается для инициализации объект с выражением инициализатора или списком выражений как его аргумент (ы). Если конструктор не применяется или разрешение перегрузки неоднозначный, инициализация плохо сформирована.

В этом случае наиболее подходящим конструктором является копия ctor, которая является частной, поэтому сообщение об ошибке.

Чтобы ответить на ваш вопрос, когда копия ctor является частной, вашей программе просто не разрешается проходить проверку соответствия, поскольку правила, установленные стандартом. Когда вы делаете копию ctor общедоступной, программа становится действительной, но вызов копии ctor оптимизирован.

EDIT: Хорошо, чтобы уточнить предыдущий параграф. Вы имеете дело с так называемым copy elision. Несмотря на то, что в этом случае возможно использование копии, стандарт требует, чтобы вы предоставили доступную копию ctor для своего класса.

Ответ 2

exampleClass e1=exampleClass();

Сначала создается временный exampleClass с использованием конструктора по умолчанию, а затем копируется в e1 с помощью конструктора копирования. Это вызовет конструктор частной копии и, таким образом, даст вам ошибку. Корреспондентский способ создания экземпляра класса со стандартным конструктором заключается в следующем:

exampleClass e1;

Ответ 3

Требуется, чтобы компилятор был там. Хотя копия может быть удалена, стандарт требует, чтобы конструктор копирования был доступен для этого типа конструкции. Конечно, вы можете упростить код и вообще избежать создания копии:

exampleClass e1; // Will call exampleClass::exampleClass()

Ответ 4

exampleClass e1=exampleClass();

совпадает с:

exampleClass e1(exampleClass());

i.e вызывает вызов (private) конструктора копии.

Ответ 5

Это связано с тем, что во время компиляции компилятор проверяет, действительно ли функция, к которой пользователь пытается получить доступ. Поэтому, когда вы используете exampleClass e1=exampleClass();, он сначала проверяет, доступен ли конструктор-копир. Он выплевывает ошибку, потому что экземпляр-конструктор не является закрытым. Помните, что на данный момент компилятор не вышел на этап оптимизации, где он делает умные вещи, чтобы пропустить конструктор-копию.

Когда вы создаете конструктор-копию public, компилятор успешно проходит этап анализа кода и следит за тем, чтобы все было доступно и в порядке (на самом деле это больше, чем это происходит), а затем на этапе оптимизации, который обычно находится в режиме "Release", он делает умный материал и обходит использование copy-constructor. Однако, если вы попробовали один и тот же код в режиме "Отладка", вы увидите, что конструктор копирования вызывает вызов.

Ответ 6

Все объясняют, как вы должны создавать экземпляр объекта, а @Grigory Javadyan отлично подходит для копирования. Похоже, MSVC делает эту оптимизацию (так называемую оптимизацию возвращаемого значения) даже в режиме отладки.

exampleClass e1=exampleClass();

совпадает с

exampleClass giveExample()
{
  return exampleClass();
}

exampleClass e1 = giveExample();

Вы увидите, что копия ctor не будет вызываться.

Но здесь:

exampleClass giveExample()
{
  exampleClass example;
  return example;
}

exampleClass e1 = giveExample();

вы увидите еще одну выходную строку:

in the copy ctor

Потому что вы вынуждаете компилятор сначала генерировать объект, а затем возвращать его.

Здесь, здесь и здесь некоторые вопросы, которые я могу найти, похожие на ваши.

PS. Ссылка № 2 находится на другом сайте Q & A. Надеюсь, это не проблема.

Ответ 7

Это потому, что конструктор копирования является закрытым.

ваш код

  • создание временного примераClass и вызов конструктора по умолчанию exampleClass()
  • попытка присвоить полученный временный объект e1 с помощью частного конструктора копирования

Ответ 8

Это не то, как вы создаете экземпляр объекта на С++. Если вы хотите, чтобы он был выделен в стеке, вы пишете:

exampleClass e1;

и вы закончили, так как конструктор exampleClass не принимает никаких параметров.

В противном случае, если вы хотите, чтобы он был выделен в кучу, вы пишете:

exampleClass e1 = new exampleClass(); 

То, как вы его написали, фактически создает временный объект и вызывает конструктор копирования на этом временном объекте для создания e1. Проблема в том, что ваш copy-ctor является конфиденциальным, поэтому сообщение об ошибке компилятора.

Ответ 9

когда вы пишете

exampleClass e1 = exampleClass() 

это то же самое, что писать

exampleClass e1( exampleClass() );

который вызывает копию ctor.