Передача указателя через параметры

 

Я, в принципе, именно так и делаю, но как-то странно выглядит код. Или может быть просто это странно из-за отсутствия опыта плотной в работы с С++. В общем, возник вопрос.

У меня есть места, где создаётся экземпляр класса и этот экземпляр нужно потом передавать по цепочке из метода в метод. Я есс-но понимаю, что по ссылке передаётся объект по значению т.е. его состояние, а по указателю объект передаётся по адресу т.е. передаётся сам адрес экземпляра класса.

Там вот в каком-то месте функции я создаю объект:

  SymbolInstance *symbol = new SymbolInstance(request.symbol);

И этот объект дальше мне нужно передавать в функцию, которая расположена в этом методе, где объект создан. Я вот и думаю, как лучше передавать экземпляр. По ссылке или по указателю?

Вот получается у меня так выглядит вызывающая функция:

bool OrdersHandling :: checkLevelsBLOCK(MqlTradeRequest& request,             // Структура торгового запроса
                                        int     operationType,                // Тип проводимой операции: 1 - Close/Del; 2 - Send; 3 - Modify;
                                        double& newOpenPrice,                 // Новая цена открытия
                                        double  newSL,                        // Новый Stop-Loss ордера
                                        double  newTP,                        // Новый Take-Profit ордера
                                        bool&   isIvalidPriceCorrection) {    // Флаг первоначальной коррекции отложки
//----
  // Создание указателя на класс свойств торгового инструмента
  SymbolInstance *symbol = new SymbolInstance(request.symbol);

  bool existStopLevel = symbol.stopLevel() > 0 ? checkStopLevelDemand(request, symbol, operationType, newOpenPrice, newSL, newTP, isIvalidPriceCorrection) :  false;
  bool existFreezeLevel = symbol.freezeLevel() > 0 ? checkFreezeLevelDemand(request, symbol, operationType, newOpenPrice, newSL, newTP) : false;

  // Удаление указателя на класс торгового инструмента
    delete symbol;

  if ((existStopLevel == true) && (existFreezeLevel == true))
    return (true);
  return (false);
}

Соответственно, эта функция checkLevelsBLOCK() вызывает функцию checkStopLevelDemand(). Вот начало функции checkStopLevelDemand():

bool OrdersHandling :: checkStopLevelDemand(MqlTradeRequest& request,              // Структура торгового запроса
                                            SymbolInstance *symbol,                // Указатель на класс свойств торгового инструмента
                                            int     operationType,                 // Тип проводимой операции: 1 - Close/Del; 2 - Send; 3 - Modify;
                                            double& newOpenPrice,                  // Новая цена открытия
                                            double  newSL,                         // Новый Stop-Loss ордера
                                            double  newTP,                         // Новый Take-Profit ордера
                                            bool&   isIvalidPriceCorrection) {     // Флаг первоначальной коррекции отложки
  bool   existStopLevel = false,
         isNewOrder = false;
  double marketPrice = 0.0;

Верно я передал указатель symbol на класс SymbolInstance ? Или может лучше было бы по ссылке передать так:

SymbolInstance& symbol

Я вчера и так и так пробывал передавать. Работает одинаково. Но вот как грамотнее для меня загадка. Есс-но интересует вопрос как работает быстрее, в том числе.

 

Оператор new - возвращает не сам объект (ссылку на него), а указатель на объект.

Лично я предпочитаю везде, по возможности, работать именно с указателями. Если использовать ссылки - то не всегда можно сходу понять - то ли это сам объект, то ли ссылка на него. При использовании указателей - таких вопросов не возникает.

"Как грамотно" - и так, и иначе. Быстрее - это надо смотреть, по идее, если передаем именно ссылку - то и по скорости не будет разницы.

 
Georgiy Merts:

Оператор new - возвращает не сам объект (ссылку на него), а указатель на объект.

Лично я предпочитаю везде, по возможности, работать именно с указателями. Если использовать ссылки - то не всегда можно сходу понять - то ли это сам объект, то ли ссылка на него. При использовании указателей - таких вопросов не возникает.

"Как грамотно" - и так, и иначе. Быстрее - это надо смотреть, по идее, если передаем именно ссылку - то и по скорости не будет разницы.

Я тоже, тем более указатели более гибкие, всегда можно убить объект. По скорости должно быть одинаково.

 

Еще раз глянул внимательнее. Насчет ссылки - вы не передаете объект по ссылке, а ссылку на указатель на объект, что не имеет ни какого смысла. Как написано в коде - правильно.

И еще, в MQL4/5 указатели содержат не адреса объекта, как в С++, а дескрипторы, которые генерит рантайм. Сделано для безопасности, чтобы вы не могли напрямую работать с адресами.

Тут вообще все закрыто в плане прямого доступа к памяти, как в C#. Чтобы ничего не порушить и никуда не залезть.

 
hoz:

по ссылке передаётся объект по значению т.е. его состояние, а по указателю объект передаётся по адресу

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

Отличия между указателем и ссылкой в Mql:

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

В C++ негласно принят следующий принцип использования:


Если нужно передать объект в функцию - константная ссылка, изменения объекта в функции невозможны

void func( const Type &obj )


Если нужно передать переменную или объект в функцию и там изменить - ссылка, изменения сохраняются после выхода из функции

void func( Type &obj )


Если передаваемый объект может не существовать - указатель ( = & Объект или = NULL ).

Если нужно дать возможность одному объекту взаимодействовать с другим - передать указатель и там запомнить.

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

void func( Type *obj )


Если нужно создать объект в функции - возвращение указателя из функции или возвращение указателя по ссылке.

То же, например для поиска объекта и возвращения указателя на него.

Type* func()
{
        return new Type();
}
void func ( Type *& obj )
{
        obj = new Type();
}

В последнем примере у вас в функцию передается по ссылке "указатель на объект".

Не вижу причин отклоняться от такого принципа в Mql.


По скорости работы между указателем и ссылкой разницы нет. Может есть очень незначительная, т.к. в Mql указатель перед использованием проверяется на то, что указывает на корректный объект. Но это ничтожная разница, о которой можно не переживать.

 
Ilya Baranov:

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

Отличия между указателем и ссылкой в Mql:

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

В C++ негласно принят следующий принцип использования:


Если нужно передать объект в функцию - константная ссылка, изменения объекта в функции невозможны

void func( const Type &obj )


Если нужно передать переменную или объект в функцию и там изменить - ссылка, изменения сохраняются после выхода из функции

void func( Type &obj )


Если передаваемый объект может не существовать - указатель ( = & Объект или = NULL ).

Если нужно дать возможность одному объекту взаимодействовать с другим - передать указатель и там запомнить.

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

void func( Type *obj )


Если нужно создать объект в функции - возвращение указателя из функции или возвращение указателя по ссылке.

То же, например для поиска объекта и возвращения указателя на него.

В последнем примере у вас в функцию передается по ссылке "указатель на объект".

Не вижу причин отклоняться от такого принципа в Mql.


По скорости работы между указателем и ссылкой разницы нет. Может есть очень незначительная, т.к. в Mql указатель перед использованием проверяется на то, что указывает на корректный объект. Но это ничтожная разница, о которой можно не переживать.

Четко сказано, Вы преподаванием занимаетесь?

 
Ilya Baranov:

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

Отличия между указателем и ссылкой в Mql:

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

В C++ негласно принят следующий принцип использования:


Если нужно передать объект в функцию - константная ссылка, изменения объекта в функции невозможны

void func( const Type &obj )


Если нужно передать переменную или объект в функцию и там изменить - ссылка, изменения сохраняются после выхода из функции

void func( Type &obj )


Если передаваемый объект может не существовать - указатель ( = & Объект или = NULL ).

Если нужно дать возможность одному объекту взаимодействовать с другим - передать указатель и там запомнить.

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

void func( Type *obj )


Если нужно создать объект в функции - возвращение указателя из функции или возвращение указателя по ссылке.

То же, например для поиска объекта и возвращения указателя на него.

В последнем примере у вас в функцию передается по ссылке "указатель на объект".

Не вижу причин отклоняться от такого принципа в Mql.


По скорости работы между указателем и ссылкой разницы нет. Может есть очень незначительная, т.к. в Mql указатель перед использованием проверяется на то, что указывает на корректный объект. Но это ничтожная разница, о которой можно не переживать.

Есть еще: const *ptr / *const ptr / const *const ptr   => это чтобы то, что передается указателями не могло изменяться.

 
Andrey Barinov:

Есть еще: const *ptr / *const ptr / const *const ptr   => это чтобы то, что передается указателями не могло изменяться.

не пробовал изменить указатель в mql, тут же не указатели, а дескрипторы, это не С++

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

 
Alexey Volchanskiy:

не пробовал изменить указатель в mql, тут же не указатели, а дескрипторы, это не С++

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

какя ошибка? указатель в данном случае как любая другая переменная, которой можно присваивать значения.

 
hoz:

Я, в принципе, именно так и делаю, но как-то странно выглядит код. Или может быть просто это странно из-за отсутствия опыта плотной в работы с С++. В общем, возник вопрос.

У меня есть места, где создаётся экземпляр класса и этот экземпляр нужно потом передавать по цепочке из метода в метод. Я есс-но понимаю, что по ссылке передаётся объект по значению т.е. его состояние, а по указателю объект передаётся по адресу т.е. передаётся сам адрес экземпляра класса.

Там вот в каком-то месте функции я создаю объект:

И этот объект дальше мне нужно передавать в функцию, которая расположена в этом методе, где объект создан. Я вот и думаю, как лучше передавать экземпляр. По ссылке или по указателю?

Вот получается у меня так выглядит вызывающая функция:

Соответственно, эта функция checkLevelsBLOCK() вызывает функцию checkStopLevelDemand(). Вот начало функции checkStopLevelDemand():

Верно я передал указатель symbol на класс SymbolInstance ? Или может лучше было бы по ссылке передать так:

Я вчера и так и так пробывал передавать. Работает одинаково. Но вот как грамотнее для меня загадка. Есс-но интересует вопрос как работает быстрее, в том числе.

Неверно вы понимаете. Нету в MQL указателей на объекты в терминах C/C++ то есть в адресах.
В обоих случаях вы оперируете со ссылкой с стиле C#. Нечто данное свыше, через которое обращаться к объекту, сиречь его дескриптор.

по началу конечно смущает что в аргументы передаётся с "Object &", а возвращается "Object *" .. считайте что тут просто так исторически принято писать.
Даже само слово указатель это скорее пережиток и дано для "совместимости с программистами C/C++"

 
Andrey Barinov:

какя ошибка? указатель в данном случае как любая другая переменная, которой можно присваивать значения.

Это верно, я погорячился. Но при обращении, как я написал " или будет ошибка в рантайме". Ладно, я просто хотел сказать, что это не полноценные указатели, выше Максим об этом написал.