Новая версия платформы MetaTrader 5 build 3440: Новый отчет по торговому счету - страница 6

 
Renat Fatkhullin #:

Исправлено в 3440.

Renat Fatkhullin #:

Исправлено в 3440.

Спасибо, работает!
 
template <typename T>
void DeleteObject( const T &Pointer )
{
  if (::CheckPointer(Pointer) == ::POINTER_DYNAMIC)
    delete Pointer;
}

class MYOBJ
{
  MYOBJ *Obj1;
  const MYOBJ *Obj2;

public:
  void Func()
  {
    DeleteObject(this.Obj1); //'Obj1' - constant variable cannot be passed as reference
    DeleteObject(this.Obj2); //Ошибки нет
  }
};

void OnStart() {}

Последняя релизная мт5 3440. Что-то перемудрили с const. В прошлой релизной собиралось норм.

 
traveller00 #:

Последняя релизная мт5 3440. Что-то перемудрили с const. В прошлой релизной собиралось норм.

собиралось, потому что был баг. теперь его исправили (читайте описание релиза п.10)

Теперь надо так:

void DeleteObject( const T * const & Pointer )

P.S. ну или так  void DeleteObject( const T * const Pointer ).  (ссылка нужна для массива указателей).
 
mktr8591 #:

собиралось, потому что был баг. теперь его исправили (читайте описание релиза п.10)

Просьба пояснить, в чем была раньше засада?

Теперь надо так:

class A{};

template <typename T>
void foo( const T &b ) {} // Раньше только этой функции было достаточно.

template <typename T>
void foo( const T* const &b ) {} // Теперь нужно дублировать еще и такой сигнатурой.

void OnStart()
{
  A a;
  A *b = NULL; 
  
  foo(a);
  foo(b);
}

Вижу, что гибкость потеряна. Ради этого?

class A{};

template <typename T>
void foo( T &b ) {} // Отказываемся полностью от const, тогда одной сигнатуры хватает.

void OnStart()
{
  A a;
  A *b = NULL; 
  
  foo(a);
  foo(b);
}
 
fxsaber #:

Просьба пояснить, в чем была раньше засада?

Вижу, что гибкость потеряна. Ради этого?

Была дыра - можно было неявно и нечевидно переменной типа A* присвоить const A*. Это описано и в форуме и в пресс-релизе.

По  вашему примеру: здесь проблема в другом. Есть отличие(недоработка?) MQL от C++.

В C++ шаблон (const T &b) эквивалентен (T const &b)   и  при получении аргумента вида A*b  разворачивается в (A* const &b). поэтому там одного этого шаблона достаточно.

 
mktr8591 #:

Была дыра - можно было неявно и нечевидно переменной типа A* присвоить const A*. Это описано и в форуме и в пресс-релизе.

Грубо говоря, раньше был хитрый способ сделать такое.

class A{};

void OnStart()
{
  A* a = NULL;
  
  const A* b = a;
  a = b; // '=' - cannot convert from const pointer to nonconst pointer
  
  A* c = a;  
  a = c; // OK
}

Похоже, туплю. Но концептуально не понимаю, какая потенциальная проблема в таком присваивании?

 
fxsaber #:

Грубо говоря, раньше был хитрый способ сделать такое.

Похоже, туплю. Но концептуально не понимаю, какая потенциальная проблема в таком присваивании?

Есть и простой способ сделать то же самое:  a=(A*)b;

идея в том, чтобы программист, который заботится о сохрании константности данных, случайно не накосячил. Сходу могу обрисовать 2 области применения:

1. Внутри одного скоупа. Если бы вы в своем примере не инициализировали

  const A* b = a;

а создали бы новый объект или инициализировали другим указателем на константу, то в "а" не присвоился бы указатель на *b.

Здесь ответственность программиста, чем инициализирует.

2. При передаче указателя в функцию. Если параметр объявлен как const X*, и надо, допустим, сохранить его значение в локальной переменной, и потом случайно не изменить объект по указателю, то надо объявить эту локальную переменную как const X*.

.. не могу сейчас привести хороших примеров из жизни.

 
mktr8591 #:

Есть и простой способ сделать то же самое:  a=(A*)b;

идея в том, чтобы программист, который заботится о сохрании константности данных, случайно не накосячил. Сходу могу обрисовать 2 области применения:

1. Внутри одного скоупа. Если бы вы в своем примере не инициализировали

а создали бы новый объект или инициализировали другим указателем на константу, то в "а" не присвоился бы указатель на *b.

Здесь ответственность программиста, чем инициализирует.

2. При передаче указателя в функцию. Если параметр объявлен как const X*, и надо, допустим, сохранить его значение в локальной переменной, и потом случайно не изменить объект по указателю, то надо объявить эту локальную переменную как const X*.

.. не могу сейчас привести хороших примеров из жизни.

Спасибо. Понимаю и везде именно для самоконтроля использую const. Очень удобно, когда компилятор подсказывает, что я кое о чем забыл и так то делать было нельзя. Реально подсказывает и плохо понимаю тех, кто const не использует в своем коде.

Видимо, концептуально разное видение этой записи.

const A* a = new A;

  1. Указатель на объект, который просто нельзя через этот указатель менять.
  2. Указатель на принципиально неизменяемый объект. И эту неизменяемость объекта нельзя поменять никаким способом, а не только через данный указатель.
Воспринимал, похоже, правильным первый вариант. А должен быть второй.
 
fxsaber #:

  1. Указатель на объект, который просто нельзя через этот указатель менять.
  2. Указатель на принципиально неизменяемый объект. И эту неизменяемость объекта нельзя поменять никаким способом, а не только через данный указатель.
Воспринимал, похоже, правильным первый вариант. А должен быть второй.
class A{};

void OnStart()
{
  const A* b = new A;
  A* a = (A*)b; // Почему так можно?!
}

Ерунда получается. Нет принципиально неизменяемого объекта.

ЗЫ Весь смысл п.10 обновления рушится такой записью.
 
What is the difference between const int*, const int * const, and int const *?
What is the difference between const int*, const int * const, and int const *?
  • 2009.07.17
  • ultraman ultraman
  • stackoverflow.com
I always mess up how to use , , and correctly. Is there a set of rules defining what you can and cannot do? I want to know all the do's and all don'ts in terms of assignments, passing to the functions, etc.
Причина обращения: