Делают ли конструкторы то же самое, что и оператор '='?

  1. Когда мы не определили ни одного оператора =, как компилятор узнает использовать конструкторы?
  2. Разве конструктор не вызывается только при определении переменной?
#include <string>

class Person
{
    public:
    std::string name;
    Person(const char* full_name) : name(full_name) {}
};

int main()
{
    Person p1("Jibel Sadeghi"); // This is ok because we declared the constructor with a const char*, but...
    /* When we didn't overload the '=' operator for 'const char*',
       how the next lines don't have any errors? */
    p1 = "Ben Sadeghi";
}

Хитрость заключается в том, чтобы реализовать все 5 и записать, что происходит.

Ted Lyngmo 26.05.2023 22:36

Вы только что сообщили компилятору два способа создания Person из других типов, поэтому он делает это при необходимости. Вы можете сделать конструкторы explicit, если хотите ограничить их использование.

BoP 26.05.2023 22:37

Я не минусовал. Это был просто общий совет.

Ted Lyngmo 26.05.2023 22:37

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

BoP 26.05.2023 22:39

@Jibel Хорошо, не стоит включать это в свой вопрос.

Ted Lyngmo 26.05.2023 22:39

способы создания, Мы ничего не создаем в строках 18 и 20, а просто устанавливаем значения @BoP

Jibel 26.05.2023 22:40

Некоторые конструкторы будут неявно доступны, если вы не создадите никаких собственных конструкторов, включая неявный конструктор копирования/присваивания.

Pepijn Kramer 26.05.2023 22:40

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

Ted Lyngmo 26.05.2023 22:41

Поскольку вы не определили свой конструктор как explicit, он называется конструктором преобразования.

heap underrun 26.05.2023 22:55

@heapunderrun Это полностью меняет для меня значение конструктора, я думал, что конструктор можно использовать только при объявлении класса.

Jibel 26.05.2023 23:01

Компилятор умен. Если ему нужен X и у него есть Y, он будет искать способы превратить Y в X. Пути от Y к X иногда могут быть неожиданными.

user4581301 26.05.2023 23:06

Я считаю, что StackOverflow рекомендует голосовать против без объяснения причин. (У меня нет под рукой ссылки.) В противном случае указание причины часто приводит к неконструктивному обсуждению (или бурному обсуждению) в комментариях, а это не дискуссионный форум.

Eljay 26.05.2023 23:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
12
129
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Разве конструктор не вызывается только при определении переменной?

Нет. Конструктор используется при создании объекта (экземпляра класса).

Этот объект может храниться в переменной, или в элементе массива, или динамически распределяться, или (в случае, если у вас есть здесь) временный объект.

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

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

Person& Person::operator=(const Person& assign_from);

и оператор присваивания перемещения по умолчанию с подписью

Person& Person::operator=(Person&& move_assign_from);

Когда компилятор пытается скомпилировать

p1 = "Ben Sadeghi";

он видит, что ему нужен Person::operator=(), просматривает всех кандидатов (по умолчанию два, потому что вы не указали ни одного) и для каждого кандидата пытается преобразовать фактические параметры в типы формальных параметров.

Для присваивания копии формальный параметр имеет тип const Person&, фактический параметр имеет тип const char[12], и существует неявный конструктор, способный выполнять преобразование. Так можно назвать Person::Person(const char*), а затем Person& Person::operator=(const Person&).

Для назначения перемещения формальный параметр имеет тип Person&&, фактический параметр имеет тип const char[12], и существует неявный конструктор, способный выполнять преобразование. Так можно назвать Person::Person(const char*), а затем Person& Person::operator=(Person&&).

Аргумент Person&& лучше подходит для временного человека, чем const Person&, поэтому в конце выбирается последовательность Person::Person(const char*), за которой следует Person& Person::operator=(Person&&).

@fabian: Ах да, перемещение по умолчанию было бы отклонено, если бы какой-либо из operator= был объявлен пользователем или если бы конструктор копирования был объявлен пользователем, но здесь это не так, и поэтому назначение перемещения по умолчанию не удаляется.

Ben Voigt 26.05.2023 23:13

Существует также неявное преобразование из const char[12] в const char *, чтобы вызвать Person::Person(const char *)

Peter 27.05.2023 04:36

@Peter: Да, это «бесплатное» преобразование.

Ben Voigt 28.05.2023 22:17

Другие вопросы по теме