Здравствуйте. Есть ли какие-нибудь существенные различия между такими определениями указателя:
int* a;
int *b;
Также хотелось бы выяснить, выигрывает ли в быстродействии определение типа "указатель на указатель". Стоит ли его использовать, или это является плохим стилем? Какую альтернативу можно применить, если лучше стараться избегать такого:
int var = 123;
int *ptrvar = &var;
int **ptr_ptrvar = &ptrvar;
int ***ptr_ptr_ptrvar = &ptr_ptrvar;
В первом случае с точки зрения поведения разницы нет. Где ставить '*'
в этом случае - это сугубо вопрос вкуса и используемого coding standard
.
Говорить о быстродействии в таких вопросах обычно не имеет смысла, поскольку шанс того, что передача объекта по указателю станет узким местом вашего приложения, очень близок к нулю даже под платформами типа ARM
.
Если, конечно, хочется пообсуждать, то делать это нужно, имея N
ассемблерных листингов gcc, cl, clang и icc
с разными уровнями оптимизаций, хотя у меня есть сильное подозрение, что он будет одинаков для большинства случаев.
int ***ptr_ptr_ptrvar
) очень сильно вредит читаемости кода, делать это следует только в случаях, когда без этого действительно не обойтись (в 99% случаев это - bad code smell
).Если вам нужно, чтобы значение переменной var
изменялось в функции, передавайте ее по указателю [C99]
или иногда, если удобнее, то по ссылке [C++03
]. Некоторые стандарты явно запрещают передачу переменной с семантикой out
по неконстантной ссылке и требуют для этого использования указателя.
Существенных отличий нет, скорее дело вкуса. Однако следует обратить внимание на следующий момент - несмотря на то, что указатель относится к типу (т.е. тип переменной : указатель на int, или указатель на char), запись вида :
int *a, b, c;
вовсе не будет означать, что у Вас описаны 3 указателя на int, - это 1 указатель и 2 переменных типа int.
Использование многоуровневой адресации возможно, однако уровни глубже второго (указатель на указатель) применяются крайне редко, да и IMXO, запутывают программу.
Тип переменных
int* a;
int *b;
int * c;
int * qewetrye;
не различается - это всё указатели на целое.
Одинарные, двойные, тройные и т.д. указатели физически ничем не отличаются - это просто адреса в памяти. Использовать указатели вообще и тем более двойные-тройные нужно только там где они действительно нужны.
Я бы сказал, что семантически правильной является запись:
int *a;
а не:
int* a;
Хотя вроде смысл обоих записей один и тот же, а именно а
указатель на целое, но попытка написания:
int* a, b, c;
Не означает, что все три a, b и с являются указателями на целое. Семантически именно это и написано! Типа int*
- нет! А запись:
int *a, b, c;
Не вызывает никакой иллюзии. Здесь четко и явно видно что указателем является только а.
Так
int*a;
и так
int * b;
тоже годится. Количество пробелов влияет только на размер исходного файла.
Указатель на указатель обычно используют для передаче данных в функцию с целью изменения функцией самого указателя.
@Asen, искусственное "накручивание" адресов применять не надо.
По поводу быстородействия - точно не ускорит.
int* a;
и int *b;
эквивалентны.Разница появляется в том, что когда нужно в одну строчку объявить несколько указателей. Например:
int* a, b, c; // a - указатель, b и с - просто целочисленные переменные
int* d,*e,*f; // здесь определено три указателя: d, e, f
В случае с применением конструкция typedef
и #define
получается интереснее.
#define P_INT int*
typedef int* PINT;
P_INT d, e, f; // указатель ТОЛЬКО d.
PINT a, b, c; // все три являются указателями
Внимание, тут явная ошибка, которую стоит обходить :-) И это еще один повод не пользоваться define
.
Указатель на указатель - это хорошо. По сути мы экономим память (указатель занимает мало места), вместо того, чтобы хранить сами копии объектов целиком, но ценой дополнительного времени на разыменование указателя. С точки зрения использования - вижу смысл использовать такую конструкцию для организации многомерных указателей или изменения значения указателя в ф-циях. А вот разумное применение для указателей на указатели на указатели уже сложно придумать.
int var = 123;
auto ptrvar = &var;
auto ptr_ptrvar = &ptrvar;
auto ptr_ptr_ptrvar = &ptr_ptrvar;
cout<< " var= " << ***ptr_ptr_ptrvar <<"\n";
// обычно разыменовывание указателя очень быстрая операция. но нужно смотреть на компилер
// если хочется передавать данные через * то лучше так:
vector (const vector &); // Конструктор копирования (медленный)
vector (vector &&); // Конструктор переноса из временного объекта (быстрый)
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Всем привет! Когда клиент отправляет серверу(или наоборот) буфер данных сделанное с помощью boost::asio::streambuf то данные как то смещаются и на выходе...
Пытался написать код на внедрение библиотеки в только что созданный процесс, но что-то не получаетсяФункция inject возвращает true, но сама библиотека...
В каких случаях нужно наследоваться от std :: enable_shared_from_this и зачем это делать? Увидел в примерах boost asio наследование от enable_shared_from_this, что это...