Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Известно, что обращение к переменной по указателю type* осуществляется в два шага: считывание адреса из указателя, переход по адресу. В то же время ссылка type& содержит прямой адрес на значение переменной в памяти, поэтому обращение по ссылке занимает на один шаг меньше. При выполнении высокопроизводительных операций эта разница ощутима. Возникает вопрос - как динамически изменить адрес ссылки, если заранее неизвестно, где будет расположена связанная со ссылкой переменная. Для наглядности рассмотрим пример: Код: plaintext 1. 2. 3. Аналогичная операция со ссылками: Код: plaintext 1. 2. 3. Возможно, возникнет вопрос - зачем это все нужно. Поясню, в моей задаче есть массив структур, содержащих статические (в смысле не изменяемые) и динамические переменные. Динамические переменные нужно часто обнулять и в некоторые из них загонять новые значения. Делать это нужно много миллионов раз, поэтому было бы выгодно вместо переменных использовать ссылки на элементы массива, который можно эффективно обнулять с помощью memset, а заполнять из кеша с помощью memcopy. Это гораздо быстрее циклического перебора структур с обращением к каждой динамической переменной. Беда в том, что количество структур заранее неизвестно, поэтому неизвестен размер массива, а значит на момент создания структуры нам нечем проинициализировать ссылку и ее придется инициализировать позже. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2013, 21:40 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybsИзвестно, что обращение к переменной по указателю type* осуществляется в два шага: считывание адреса из указателя, переход по адресу. В то же время ссылка type& содержит прямой адрес на значение переменной в памяти, поэтому обращение по ссылке занимает на один шаг меньше. При выполнении высокопроизводительных операций эта разница ощутима Это не так. На уровне машинного кода реализация указателя и ссылки одинаковая, поэтому никакой разницы в скорости у них нет. (Где вы вообще про такое прочли?) Соответственно, необходимость изменения ссылок надумана. Используйте указатели. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2013, 21:47 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyandreybsИзвестно, что обращение к переменной по указателю type* осуществляется в два шага: считывание адреса из указателя, переход по адресу. В то же время ссылка type& содержит прямой адрес на значение переменной в памяти, поэтому обращение по ссылке занимает на один шаг меньше. При выполнении высокопроизводительных операций эта разница ощутима Это не так. На уровне машинного кода реализация указателя и ссылки одинаковая, поэтому никакой разницы в скорости у них нет. (Где вы вообще про такое прочли?) Соответственно, необходимость изменения ссылок надумана. Используйте указатели. Читал на stackoverflow.com. Эксперименты показывают, что скорость отличается. Возможно, это из-за двойного преобразования. Ведь если есть double& a и double b, то вычислить сумму можно напрямую: a+b, а если есть double* a и double b, то сумма требует на одну операцию больше: *a+b (добавился переход по ссылке *). Разве не так? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2013, 22:03 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyНа уровне машинного кода реализация указателя и ссылки одинаковая, поэтому никакой разницы в скорости у них нет. Возможно, Вы правы. Я провел еще эксперимент - сравнил скорость работы указателя и ссылки. Разницы не увидел - это может косвенно подтверждать, что реализация на уровне машинного кода одинаковая. Вот что меня действительно удивило - это что доступ по ссылке работает медленнее, чем прямой доступ к переменной. Видимо, ссылка на уровне машинного кода сама реализуется, как переменная с адресом, а не константа. Непонятно только, если это не константа, то зачем было запрещать изменять ее адрес bydesign. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2013, 22:23 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybs, Нет, не так. Как - я выше уже писал: ссылки и указатели- это одно и тоже. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Теперь давайте ссылку на stackoverflow где это написано, и код который показывает отличия в скорости. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2013, 22:28 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybsНепонятно только, если это не константа, то зачем было запрещать изменять ее адрес bydesign Потому что на ссылках висят еще и разные семантические правила, которые применяются в compile-time. Если не в даваться в детали, то ссылку нельзя менять по тем же причинам, по которым нельзя поменять адрес объявленной переменной. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2013, 22:35 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyЕсли не в даваться в детали, то ссылку нельзя менять по тем же причинам, по которым нельзя поменять адрес объявленной переменной. Чтобы не приводить код к "unsafe" из-за возможных утечек памяти? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2013, 22:45 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybs, Ну не из-за утечек, но да, для безопасности кода. Также как когда мы пишем const int i = 3, то в программе мы менять значение не можем, хотя в машинном коде память доступна для записи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 00:00 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybs, ссылки (если угодно - автоматически разименуемые указатели) дают выигрыш только на больших структурах данных, а вот на "плоских" - нет. Просто потому, что размер этих данных (double, int, etc..) сравним с размером указателя, и тогда что передавать по ссылке, что по значению - всё равно. Для "плоских типов" передавать что-то по ссылке (точно так же, как и по указателю) нужно только в том случае, если "получатель" ссылки должен менять значения, и они должны "отражаться в оригинале" (при передаче по копии такие изменения в "источник" не вернутся). Для больших типов (вроде вектров, списков и т.д) экономия происходит за счёт избегания копирования большого количества элементов контейнера. Вот простой пример: int i = 10; int ii = 1000; int& j =i; cout << i << endl; j = 100; cout << i << endl; j = ii; cout << i << endl; вывод этого кода будет 10 100 1000 А вот переопределить ссылку (чтобы они сначала указывала на одну переменную, а с какого-то места - на другую) - не получится. Но вы можете для себя написать класс-обрёртку, которая будет играть эту роль. Вот только нужно ли? Похоже, что вам надо сначала сформулировать задачу, а уже потом задумываться об эффективности её решения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 10:07 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
BagaBagaА вот переопределить ссылку (чтобы они сначала указывала на одну переменную, а с какого-то места - на другую) - не получится. Но вы можете для себя написать класс-обрёртку, которая будет играть эту роль. Вот только нужно ли? Нужно. В итоге я так и сделал - шаблон class var<T>. Синтаксически с ним можно работать как со ссылкой, но при этом можно менять адрес его указателя. Так динамические переменные заменены с double на указатели vdouble (синоним var<double>). Указатель содержит адрес элемента массива, через который производятся массовые операции изменения значений динамических переменных. Есть только одно неудобство. Например, для double есть операция +=, а для bool ее нет. Поэтому перегрузку оператора += не получается включить в состав класса var<T>. Прочие операции +,-,*,/ и т.п. работают автоматически, т.к. перегружены операторы прямого-обратного преобразования: T& operator=(TT &src) // TT - любой тип будет преобразован к T и извлечено значение в указатель operator T() // возвращается значение типа T& operator TT() // возвращается значение типа T& Но для операции += этого недостаточно. Например, var<double> += double не предусмотрен, нужна перегрузка оператора += для var<T>. Интересно, можно ли это как-то обойти, явно не перегружая операторы ++,--,+=,-= ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 12:32 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybsЕсть только одно неудобство. Например, для double есть операция +=, а для bool ее нет. Поэтому перегрузку оператора += не получается включить в состав класса var<T>. А можете продемонстрировать на примере кода, что именно не получается? И кстати, зачем вам обертка для имитации ссылок, если вы можете в любой момент из указателя сделать ссылку? Код: plaintext 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 13:25 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybs, Зачем городить какие-то классы вместо указателей, а не пользоваться самими указателями? Кроме этого, умных указателей уже написано достаточно много. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 16:06 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
авторАналогичная операция со ссылками: Код: plaintext 1. 2. 3. Никак. Ссылка -- это константный разименованный указатель. Он НЕ МЕНЯЕТСЯ никогда. Это одно из основных отличий ссылки от указателя. Указатель может указывать на разные объекты в течении своей жизни, ссылка -- не может, после инициализации она указывает всегда на один и тот же объект. авторВозможно, возникнет вопрос - зачем это все нужно. Поясню, в моей задаче есть массив структур, содержащих статические (в смысле не изменяемые) и динамические переменные. Динамические переменные нужно часто обнулять и в некоторые из них загонять новые значения. Делать это нужно много миллионов раз, поэтому было бы выгодно вместо переменных использовать ссылки на элементы массива, который можно эффективно обнулять с помощью memset, а заполнять из кеша с помощью memcopy. Это гораздо быстрее циклического перебора структур с обращением к каждой динамической переменной. Беда в том, что количество структур заранее неизвестно, поэтому неизвестен размер массива, а значит на момент создания структуры нам нечем проинициализировать ссылку и ее придется инициализировать позже. Я мало что понял из этого потока сознания. Используй указатели значит, они ничем не хуже ссылок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 18:06 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyА можете продемонстрировать на примере кода, что именно не получается? Вот класс-обертка: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. Вот пример использования: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Anatoly MoskovskyИ кстати, зачем вам обертка для имитации ссылок, если вы можете в любой момент из указателя сделать ссылку? Просто пока программа не написана полностью, а работа со структурами, члены которых сейчас заменены на такие "указатели" выполняется уже во всех модулях. Поэтому переколбашивать все модули, ставя перед всеми обращениями к указателю * не удобно. Может потом, когда структура программы устаканится, я уберу класс-обертку, но пока им удобно польльзоваться и он не влияет на производительность (в сравнении со ссылками). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 20:07 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
MasterZivЯ мало что понял из этого потока сознания. Это, наверное, от того, что что тратишь много энергии на критику. Ты же считаешь, что я даже класс от объекта отличить не могу... Ну и не трать свое время на общение с неучами, как нибудь сами разберемся. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 20:12 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybs Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. А ну тут все правильно. Так как для операции d+d1 производится поиск возможных преобразований типа операндов к единому типу и для var такое преобразование есть: operator T, то все работает. А для += такого поиска преобразования не производится. Это связано с тем что операция + для встроенных типов определена как если бы она была свободной функцией, а операция += - как если бы она была методом (в этом случае потребовалось бы 2 последовательных неявных преобразования, а это запрещено правилами С++). Таким образом, вам действительно нужно в вашем шаблоне определить оператор += и прочие. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:05 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyТаким образом, вам действительно нужно в вашем шаблоне определить оператор += и прочие. А не будет ошибок при использовании типов, где эта операция не определена, например, var<bool>? Я пока не проверял, просто заменил в одном месте программы x += y на x=x+y, чтобы убрать ошибку. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:12 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Я то думал что вы определили оператор += в шаблоне и для инстанцирования bool это не работало (по вашим словам из-за отсутствия += у bool). Так вот, для bool должно работать (если конечно вы не вызываете += для var<bool>) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:14 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybsА не будет ошибок при использовании типов, где эта операция не определена, например, var<bool>? Не будет ошибок, т.к. тела шаблонов проверяются только при их явном вызове. Это относится как телам функций в шаблонных классах(а так же и другим объявлениям внутри класса), так и телам функций-шаблонов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:18 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybsMasterZivЯ мало что понял из этого потока сознания. Это, наверное, от того, что что тратишь много энергии на критику. Ты же считаешь, что я даже класс от объекта отличить не могу... Ну и не трать свое время на общение с неучами, как нибудь сами разберемся. Спасибо, что предупредил, не буду и тратить.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:18 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
andreybs, Кстати, а почему вы решили что += не определена для bool? :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:23 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
inline T& operator=(T *src) { _ptr = src; return *_ptr; } template <typename TT> inline T& operator=(const TT &src) { assert(_ptr!=NULL); *_ptr = (T)src; return *_ptr; } — Плохой стиль. Ты одновременно позиционируешь ЭТО И как указатель, и как ссылку. Плохо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:24 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovsky, Вчера как раз на этом остановился, не успел проверить. Проверил сейчас, действительно работает - главное не вызывать операцию для тех типов, где она не определена. Тут вот еще вопрос вчера возник, с которым я пока не разобрался. Мне непонятно, почему одновременно приходится прописывать: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Если убрать Т(), то перестают работать выражения вида {double} += {var<double>}, а если убрать ТТ(), то перестают работать вызовы функций F(_variant_t arg), где в качестве arg подставляется var<double>. По идее ТТ() должен полностью перекрывать Т(), но на деле как будто ТТ() рассматривается для всех типов, кроме Т (т.е. double в var<double>). При этом в аналогичной ситуации оператор =(ТТ &src) перекрывает оператор =(Т &src). Собственно мой вопрос в в том, как устроен алгоритм выбора подходящего шаблона? В частности, для конструкции template <typename TT> inline operator TT() внутри класса template <typename T> class var для реализации шаблона var<double> тип ТТ может рассматриваться, как double или нет (т.е. ТТ - это любой тип, кроме Т=double)? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:35 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
[quot andreybs]BagaBagaЕсть только одно неудобство. Например, для double есть операция +=, а для bool ее нет. Поэтому перегрузку оператора += не получается включить в состав класса var<T>. Если речь идёт о вашей обёртке, то я принципиально не вижу проблемы. Например, вот такой код Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. выводит Код: plaintext 1. 2. 3. Я намеренно не использовал шаблоны, чтобы за "деревьями" не "потерять лес". Переписать это на шаблоны нет проблем. Там, конечно, нужен будет не только оператор, принимающий double (в вашем случае - тип-параметр), но и оператор, принимающий в качестве входа "такую же обёртку" (а также аналогичный конструктор), но в данном случае это суть не изменит, а строк добавит. Для особых случаев (для тех типов, для которых операция *ptr +=d не определена) вы можете сделать специализацию шаблона и задать то поведение, которое нужно в соответствии с вашей задачей (если такая операция просто недопустима, то можно породить исключение, правда, мне это кажется нелогичным - хотеть оператор для "общего" случая и не иметь понятия о желаемом его поведении). Но я всё равно не понимаю вашей задачи (да она и не озвучена). Использование стандартного контейнера предполагает использование предоставливаемых им штатных средств. Знание того, что вектор хранит свои структуры в непрерывном "куске памяти" полезно при обеспечении совместимости с С-кодом, а вот в других случаях - это верный способ "выстрелить себе в ногу". В отличии от memset, контейнер при создании каждого элемента вызывает его конструктор, ну, и деструктор при выходе из области жизни. Простое же копирование допустимо только для "плоских" типов, что идёт в разрез со "сложными непонятно где определёнными типами". Приведу простой пример: создание простого массива (через new) и его последующая инициализация с memset по сравнению с vector<int>v(elem_number, 0) давало выигрыш менее 0.5%. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:40 |
|
||
|
изменить адрес ссылки
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovskyandreybs, Кстати, а почему вы решили что += не определена для bool? :) У меня компилятор предупреждение выдает... warning C4804: +=: небезопасное использование типа "bool" в операции Полагаю, он bool в int конвертит и работает с true=(int)1, а false=(int)0... Кривотина какая то... :) Наверное, будет работать без варнинга только для BOOL, или что там у нас определено, как int... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2013, 21:40 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38390227&tid=2019985]: |
0ms |
get settings: |
9ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
44ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
60ms |
get tp. blocked users: |
1ms |
| others: | 13ms |
| total: | 160ms |

| 0 / 0 |
