перегруженный оператор присваивания не вызывается

#c #operator-overloading

#c #перегрузка оператора

Вопрос:

Спасибо вам всем за ваши ответы. И спасибо за cppinsight и godbolt, не знал об этом.

Я отредактировал свой вопрос здесь, что я хочу сделать. По сути, у меня есть функция сбора SDK, которая имеет аргумент pointer float в качестве входных данных, и я хочу отслеживать этот аргумент в режиме реального времени, чтобы узнать статус сбора. Теперь я получил этот код для работы:

 #include <iostream>

template <class T>
class MonitoredVariable
{
public:
    MonitoredVariable() {}
   // MonitoredVariable(const Tamp; value) : m_value(value) {}

    operator Tamp;() { return m_value; }
   //operator const Tamp;() const { return m_value; }

    MonitoredVariableamp; operator = (float value)
    {
        printf("Variable modifiedn");
        this->m_value = amp;value;
        printf("%f n", *this->m_value);
   
        return *this;
    }

      MonitoredVariableamp;  operator * () {return *this;}
    
private:
    T m_value;
};

void SDKfunctionIcannotChange(float *a)
{
    *a = (float) 5.2; 
    printf("%f n", *a); // if I comment this out, x will not update?!?!
    return;
}

int main()
{
    MonitoredVariable<float*> x;
    *x=0;
    SDKfunctionIcannotChange(x);
    printf("%f n", *x);
    
return 1;
}
 

Но, как ни странно, если я закомментирую эту printf команду в SDKfunctionIcannotChange функции, то значение x не изменится. Есть какие-нибудь идеи, почему это происходит?

Так и с printf (правильно):

 Variable modified
0.000000 
5.200000 
5.200000
 

и без

 Variable modified
0.000000 
0.000000 
 

Спасибо..

Комментарии:

1. *m_value = value.m_value; это неопределенное поведение, потому что вы никогда m_value не указываете на a float . Для хранения a float вам нужно float где-то, а не просто указатель

2. *x не является экземпляром вашего класса. Поначалу неявные преобразования обычно кажутся хорошей идеей, но на самом деле это не так. Добавьте немного печати в свой.

3. float* != float .

4. Не связано: void main() недопустимо C . Сделайте это int main()

5. ps: Мой первый комментарий частично связан с тем, что я неправильно прочитал код. Тем не менее это часть проблемы, поэтому я оставляю комментарий, хотя он и не совсем корректен

Ответ №1:

Это отвечает на первоначальный вопрос перед обширным редактированием.

По сути, ваша программа эквивалентна:

 int main()
{
    float *x = nullptr;
    float y = 5;
    *x = y; // here is UB since x == nullptr
}
 

См. cppinsights: проблемная строка выглядит следующим *static_cast<float *>(x.operator float *amp;()) = y; образом. Таким образом, ваш код использует не пользовательский operator= , а оператор преобразования.
В основном проблема заключается в коде, который использует шаблон.

Я не знаю, каковы были ваши намерения, может быть, это:

 #include <iostream>

template <class T>
class MonitoredVariable
{
public:
    MonitoredVariable() {}
    MonitoredVariable(const Tamp; value) : m_value(value) {}

    operator Tamp;() { return m_value; }
    operator const Tamp;() const { return m_value; }

    MonitoredVariableamp; operator = (const Tamp; value)
    {
        printf("Variable modifiedn");
        m_value = value; // here was also a problem
        return *this;
    }

int main()
{
    MonitoredVariable<float*> x;
    float y = 5;
    x = amp;y;

    return;
}
 

https://godbolt.org/z/js5zdz

Комментарии:

1. Альтернативой может быть создание параметра шаблона float , вместо float* которого упростилось бы использование. пример

2. Да, это еще одна интерпретация его намерения.

Ответ №2:

*x Выражение вызывается operator* с аргументом of x . Во время поиска имени найден встроенный operator* для указателей. Учитывая, что в вашем классе MonitoredVariable есть оператор преобразования в T (который в вашем случае является типом указателя), вызывается этот оператор преобразования, и возвращаемый указатель, который равен null, затем разыменовывается, вызывая сбой.

То, что вы, вероятно, хотели написать, это x = y .

Комментарии:

1. Что, если OP определил a operator* ?

2. @Lingo Тогда этот оператор был бы вызван, очевидно. Но тогда OP должен был бы также реализовать ссылочный прокси-сервер для перехвата следующего назначения. Неясно, какова цель MonitoredVariable класса, поэтому я не могу сказать, будет ли это рекомендуемым решением.