Поведение конструкторов, когда конструктор копирования определяется пользователем

0

Я пытаюсь понять конструкторы копирования, пожалуйста, поймите меня, как это работает.

Дело 1

class fruit{
    public: int i;
            fruit(int j){
               i = j;
            }
};

int main(){
   fruit f1 = fruit(2); // works fine when no user defined copy constructor
   return 0;
}

Случай 2

class fruit{
    public: int i;
            fruit(fruit &f){
               i = f.i + 1;
            }
            fruit(int j){
               i = j;
            }
};

int main(){
   fruit f1 = fruit(2); // error no matching call fruit::fruit(fruit) why?
   return 0;
}

Случай 3

class fruit{
    public: int i;
            fruit(){
               i = 0;
            }
};

int main(){
   fruit f2;
   fruit f1 = fruit(f2); // works fine when no user defined copy constructor
   return 0;
}

Случай 4

class fruit{
    public: int i;
            fruit(){
               i = 0;
            }
            fruit(fruit &f){
              i = f.i + 1;
            }
};

int main(){
   fruit f2;
   fruit f1 = fruit(f2); // error no matching call fruit::fruit(fruit)
   return 0;
}
Technically 'fruit(f2)' must be valid because 
f2 can be passed by reference to fruit(fruit &f). right? but why error?

Почему я получаю ошибку в Case 2 и Case 4? это потому, что я создал пользовательский конструктор копирования? Если причиной является пользовательский конструктор копирования, даже компилятор предоставляет конструкторы копирования по умолчанию. как fruit(fruit &) внутри. Так что даже тогда конструкторы копирования доступны для программы, предоставляемой компилятором. Почему это не вызывает ошибки в случаях Case 1 и Case 3

Я понимаю, что все конструкторы заблокированы с = когда пользователь определяет конструктор копирования. = может вызвать только конструктор копирования. но должен быть один конструктор копирования для класса может быть пользователем или компилятором. Если он предоставляется компилятором, то он также должен вызывать ошибку. но это не так?

  • 0
    fruit(fruit&) не является конструктор копирования, просто обычный конструктор , который требует L-значение fruit ссылки. fruit(fruit const&) является конструктором копирования, а fruit(fruit&&) является конструктором перемещения, который будет вызываться (если предоставлен) с учетом ваших примеров. Это потому, что вы создаете временные объекты, которые не являются l-значениями, и поэтому не могут быть привязаны к ссылкам l-значения ( & ), но могут быть привязаны к ссылкам r-значения ( && ).
  • 1
    @Cameron: Да, это конструктор копирования. Не такой полезный, как тот, который принимает константную ссылку, но точно такой же конструктор копирования.
Показать ещё 2 комментария
Теги:

2 ответа

2
Лучший ответ

Это не проблема, связанная с конструкторами копирования; Ссылки non- const lvalues не могут привязываться к временным.

Следующий код был бы скомпилирован:

fruit f1;
fruit f2(f1);

потому что f1 не является временным, когда вы его передаете.

Тем не менее, вы хотите, чтобы временные файлы работали, поэтому напишите свой конструктор копирования следующим образом:

fruit(const fruit& f) {
   i = f.i + 1;
}

Ваши случаи 1 и 3 преуспевают, потому что компилятор может создать собственный конструктор копии по умолчанию, увидев, что вы его не предоставили, что в отличие от вас - оно работает правильно. :-)

  • 0
    Не могли бы вы объяснить, почему дело 2 терпит неудачу? Я передаю целое число, почему компилятор проверяет фрукты (фрукты)?
  • 0
    @ user3205479: Вы передаете целое число в fruit(int) , который работает нормально .... но затем вы копируете получившийся временный объект в f1 и это происходит по той же причине, что и в других случаях. Если бы вы только что написали fruit f1(2); тогда это сработало бы, потому что для этого не нужно копировать какие-либо фрукты.
Показать ещё 3 комментария
1
fruit f1 = fruit(f2);

Для фруктов (f2) будет создано временное, которое не может быть привязано к неконстантной ссылке. Для этого вам необходимо использовать следующую копию:

fruit(const fruit& f)
  • 0
    Я уже сказал это.
  • 0
    Не могли бы вы объяснить, почему дело 2 терпит неудачу? Я передаю целое число, почему компилятор проверяет наличие фруктов (fruit)
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню