Nano Hash - криптовалюты, майнинг, программирование

Невозможно понять перегрузку оператора присваивания

Чтобы лучше понять работу объектов в С++, я написал этот фрагмент кода:

using namespace std;

char n[] = "\n";

class T
{
  private:
    int num;

  public:
    T ()
    {
        num = 0;
        cout << n << (long)this % 0xFF << " created without param";
    }

    T (const int param)
    {
        num = param;
        cout << n << (long)this % 0xFF << " created with param = " << param;
    }

    T (const T& obj)
    {
        num = obj.num;
        cout << n << (long)this % 0xFF << " created as copy of " << (long)&obj % 0xFF;
    }

    const T& operator= (const T& obj)
    {
        if (this == &obj)
            return *this;
        num = obj.num;
        cout << n << (long)this % 0xFF << " got assigned the data of " << (long)&obj % 0xFF;
        return *this;
    }

    ~T ()
    {
        cout << n << (long)this % 0xFF << " destroyed";
    }

    int get () const {return num;}
    void set (const int param) {num = param;}
};

T PlusTen (T obj)
{
    T newObj(5);
    newObj.set( obj.get() +10 );
    return newObj;
}

int main ()
{
    T a, b(4);
    a = b;
    a = PlusTen(b);

    cout << n;
    return 0;
}

Он работает нормально, но когда я удаляю квалификатор const в «типе возврата» и «параметре» перегруженного оператора присваивания, как показано ниже:

T& operator= (T& obj) // const removed
{
    if (this == &obj)
        return *this;
    num = obj.num;
    cout << n << (long)this % 0xFF << " got assigned the data of " << (long)&obj % 0xFF;
    return *this;
}

Затем эта строка основной функции дает ошибку:

a = PlusTen(b);

Сообщение об ошибке:

no match for 'operator=' (operand types are 'T' and 'T')
    note:
    candidate is: T& T::operator=(T&)
    no known conversion for argument 1 from 'T' to 'T&'

Если типы операндов 'T' и 'T' проблематичны, то почему строка над ними (a = b;) полностью исправна? Они тоже имеют типы операндов 'T' и 'T' !!


Я нашел здесь соответствующий вопрос, но не нашел там полезной информации:
почему вы должны указывать ключевое слово const в перегрузках операторов
Один человек говорит, что если мы не используем const в operator=, мы можем использовать его только для non-const объектов. Но и в моем случае обе стороны неконстантны. Тогда почему ошибка? Особенно, когда строка над ней, идентичная по типам операндов, компилируется нормально?


Используемый компилятор: MinGW


Ответы:


1

Эта функция

T PlusTen (T obj)
{
    T newObj(5);
    newObj.set( obj.get() +10 );
    return newObj;
}

возвращает временный объект типа T. этот временный объект может быть связан с постоянной ссылкой.

Это важно! Это причина, по которой OP запутался!
Неконстантные ссылки на временные объекты не разрешены в C++ !! Вот почему преобразование T в const T удалось в a = b;, но не удалось в a = PlusTen(b);, потому что RHS в последнем является временным.

Поэтому компилятор выдает ошибку, потому что параметр оператора присваивания

T& operator= (T& obj)
              ^^^^^^

не является постоянной ссылкой.

Квалификатор const в возвращаемом типе не имеет значения в контексте того, как оператор используется в вашей программе.

22.03.2016

2

PlusTen(b); создает временный объект. Поскольку неконстантные ссылки не могут быть привязаны к временным объектам, здесь нельзя вызывать operator=.

В a = b; b не является временным, это изменяемый объект (так называемое l-значение). К нему успешно привязывается неконстантная ссылка, и вызывается operator=.

Для дополнительного удовольствия попробуйте определить свой b следующим образом:

const T b(4);
22.03.2016
Новые материалы

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

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..