Ошибки, баги, вопросы - страница 1951

 
Stanislav Korotky:

Можно ли каким-либо образом вернуть анонимный экземпляр объекта из функции?

Заменить на макрос.
 
fxsaber:
Заменить на макрос.

Не получится. Это метод класса и param на самом деле берется из объекта. Тут для примера я упростил.

 
Stanislav Korotky:

Не получится. Это метод класса и param на самом деле берется из объекта. Тут для примера я упростил.

Лучше, конечно, ознакомиться с исходной задачей...

Вернуть указатель - будет не то?

 

Stanislav Korotky:

Он работает, за исключением того, что создается лишняя внутренняя копия, а оператор return требует наличия копи-конструктора в классе. Хотя копия и прибивается при выходе из функции, само копирование хотелось бы исключить.


Class function()
{
  int param = 0;
  Class obj(param);
  return obj;
}

Конечно требует, после выхода из функции локальная переменная уничтожается.
Используйте new и возвращайте указатель, в чем проблема?

Если нужен контроль ресурсов, используйте обертку на подобии смарт указателя.
Возможно вам подойдет что-то с Creational Patterns типа синглтона или строителя, ...

 
fxsaber:

Лучше, конечно, ознакомиться с исходной задачей...

Вернуть указатель - будет не то?

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

 
Sergey Dzyublik:

Конечно требует, после выхода из функции локальная переменная уничтожается.

Используйте new и возвращайте указатель, в чем проблема?

Если нужен контроль ресурсов, используйте обертку на подобии смарт указателя.
Возможно вам подойдет что-то с Creational Patterns типа синглтона или строителя, ...

Указатели есть - неудобно (ответил выше). Я попробовал смотреть в сторону "смартов". Но у меня сложилось впечатление, что для MQL умный указатель только даст еще один уровень ссылочности, за которым нужно будет в свою очередь следить. Ведь что такое умный указатель? - это объект-обертка, в который положена исходная ссылка. И кто и когда будет чистить обертку? ;-) Если есть готовые решения, скиньте в личку плиз. У меня тест-кейс пока в работе.

 
Stanislav Korotky:

Ведь что такое умный указатель? - это объект-обертка, в который положена исходная ссылка. И кто и когда будет чистить обертку? ;-) Если есть готовые решения, скиньте в личку плиз. У меня тест-кейс пока в работе.


Используйте shared_ptr.
Эту обертку чистить не нужно, ее нужно копировать, а сколько экземпляров с нужным ресурсом осталось  и когда тот или иной ресурс освобождать и есть суть shared_ptr.


Готовых решений нет, по крайней мере у меня. Адаптируйте С++-сные.

 
Sergey Dzyublik:

Готовых решений нет, по крайней мере у меня. Адаптируйте С++-сные.

Это понятно - я этим и занимаюсь, но уже сложилось впечатление, что MQL не позволит сделать "кальку".

 
Stanislav Korotky:

Можно ли каким-либо образом вернуть анонимный экземпляр объекта из функции?

Как тут уже подметили, самый правильный способ - это возвращать из функции смарт-указатель. Всё это реализуемо в MQL. Правда пользоваться не так удобно как в C++, поскольку переход по указателю придётся реализовывать через метод, а не через оператор перехода.   Кстати, для рассматриваемой задачи, полагаю, необязательно shared_ptr, достаточно и unique_ptr.

Ну или как вариант, чтобы созданный указатель внутри функции сразу помещался в некий глобальный массив, который в конце работы программы бы вычищался. При этом пользователь может и сам в любой момент освободить память объекта, вызвав специальную функцию (не delete).  По аналогии как CloseHandle в WinApi.

Он работает, за исключением того, что создается лишняя внутренняя копия, а оператор return требует наличия копи-конструктора в классе. Хотя копия и прибивается при выходе из функции, само копирование хотелось бы исключить.

Возможно компилятор достаточно умён и сам всё оптимизирует и заинлайнит, исключив ненужное копирование. Но это надо проверить. Было бы хорошо, если бы кто-то провёл тесты и замеры.  А то я сам тоже часто озадачиваюсь такой дилеммой.

 
Alexey Navoykov:

Как тут уже подметили, самый правильный способ - это возвращать из функции смарт-указатель. Всё это реализуемо в MQL. Правда пользоваться не так удобно как в C++, поскольку переход по указателю придётся реализовывать через метод, а не через оператор перехода.   Кстати, для рассматриваемой задачи, полагаю, необязательно shared_ptr, достаточно и unique_ptr.

Ну или как вариант, чтобы созданный указатель внутри функции сразу помещался в некий глобальный массив, который в конце работы программы бы вычищался. При этом пользователь может и сам в любой момент освободить память объекта, вызвав специальную функцию (не delete).  По аналогии как CloseHandle в WinApi.

Возможно компилятор достаточно умён и сам всё оптимизирует и заинлайнит, исключив ненужное копирование. Но это надо проверить. Было бы хорошо, если бы кто-то провёл тесты и замеры.  А то я сам тоже часто озадачиваюсь такой дилеммой.

Свою реализацию публикую ниже - все равно эти смарт-указатели создаются временные, и в результате просто создается и прибивается больше объектов чем было ;-).

Вариант про глобальный массив я конечно держу в уме, но насколько же это некрасиво! Тем более, что я хотел чистить по таймеру (ибо программа может работать днями), а таймер в MQL нельзя привязать к классу/объекту - он только из глобального обработчика подхватывается.

Компилятор тут не помогает - проверено - локальный объект по return-у дублируется и затем прибивается. Оптимального в данном случае переноса (move) нет.

template<typename T>
class auto_ptr
{
  private:

    class Reference
    {
      public:
        int count;
        Reference(): count(0) {}
    };

    T *data;
    Reference *reference;

    void remove()
    {
      if(reference != NULL)
      {
        reference.count--;
        if(reference.count == 0)
        {
          delete data;
          delete reference;
        }
      }
    }

    
  public:
    auto_ptr(): data(NULL), reference(NULL)
    {
    }
    auto_ptr(T *ptr): data(ptr), reference(ptr == NULL ? NULL : new Reference())
    {
      if(reference != NULL) reference.count++;
    }
    auto_ptr(auto_ptr<T> &ref): data(ref.data), reference(ref.reference)
    {
      reference.count++;
    }
    
    ~auto_ptr()
    {
      remove();
    }
    
    void operator=(auto_ptr<T> &next)
    {
      if(&this != &next)
      {
        remove();
        
        data = next.data;
        reference = next.reference;
        reference.count++;
      }
    }
};
Причина обращения: