Проблема неявного преобразования в конструкторе копирования - PullRequest
0 голосов
/ 02 февраля 2020

Часть ответа дана в здесь

class foo1
{
private:
        int i;
public:
        foo1()  
        {
           i=2;
        }
        int geti(){
                return i;
        }
};

class foo2
{
private:
        int j;
public:
        explicit foo2(foo1& obj1) //This ctor doesn't have `const` intentionally as i wanted to understand the behavior.

        {
                cout<<"\nctor of foo2  invoked";
                j=obj1.geti();
        }
};

    foo1 obj1;
    foo2 obj2(obj1); //THIS WORKS

    foo2 obj22=obj1; //THIS DOESN'T WORK

Они оба работают, когда удалена клавиатура explicit.

Верно ли следующее объяснение для инициализации копии (foo2 obj22=obj1):

Сначала компилятор создает временный объект, используя конструктор: foo2(foo1& other) {}, затем он пытается использовать этот временный объект в конструкторе копирования: foo2(foo2& other) {} Но это может не связать временный объект с непостоянной ссылкой, и это выдает ошибку. Когда вы используете знак равенства, тогда используется так называемая инициализация копирования.

Если да, то не следует запрещать саму foo2(foo1& other) {}, прежде чем идти дальше, потому что временное не может быть связано с неконстантная ссылка?

Извините за длинный вопрос, моя путаница в основном связана с поведением различий для прямой инициализации и копирования при наличии / отсутствии явного ключевого слова (с / без константы)

1 Ответ

1 голос
/ 02 февраля 2020

Правильно ли следующее объяснение для инициализации копирования

Это не так. Вы опустили определение копии c 'tor для foo2. Это означает, что компилятор автоматически его синтезирует. Синтезированная версия займет у const foo2&. Таким образом, проблема заключается в , а не в привязке временного foo2 к неконстантной ссылке.

На самом деле, инициализация копирования больше не создает временных и даже не имеет вести себя так, как будто временный присутствует. Вместо этого происходит то, что форма инициализации просто принимает во внимание ключевое слово * 1012.

Оба эти

foo2 obj2(obj1); 
foo2 obj22=obj1; 

выполняют одинаковое разрешение перегрузки, которое может выбирать только одно и то же c 'tor (foo2(foo1& obj1)). Он должен выбрать это c ', потому что вы передаете неконстантное lvalue для аргумента.

Разница? Прямой инициализации разрешено использовать явный c 'tor. Пока инициализации копии нет. Таким образом, ваш явный c 'tor не является кандидатом, и разрешение перегрузки не выполняется.

...