Punctuation: replace --/--- with —.

This commit is contained in:
Lapshin Dmitry (LDVSOFT)
2021-01-25 17:32:50 +03:00
parent 3c1d2a51d4
commit 1c3f97d4a9
20 changed files with 118 additions and 118 deletions
+14 -14
View File
@@ -3,10 +3,10 @@
Что вообще такое указатель?
Когда их пытаются объяснить новичкам в C++, часто говорять, что это число, адрес, указывающий на номер ячейки в памяти, где что-то лежит.
Это в каком-то смысле справедливо на очень низком уровне -- в ассемблере, в машинных кодах. Но В C/С++ указатель это не просто адрес. И тем более не число, которое как-то просто по-особому используется.
Более того, в C++ (не в C), есть указатели, которые вообще не являются адресами в памяти -- указатели на поля и методы классов. Но о них мы говорить сейчас не будем.
Это в каком-то смысле справедливо на очень низком уровне в ассемблере, в машинных кодах. Но В C/С++ указатель это не просто адрес. И тем более не число, которое как-то просто по-особому используется.
Более того, в C++ (не в C), есть указатели, которые вообще не являются адресами в памяти указатели на поля и методы классов. Но о них мы говорить сейчас не будем.
Указатель -- это ссылочный тип данных. Нечто, с помощью чего, можно получить доступ к другим объектам. И, в отличие от C++-ссылок, объекты-указатели являются настоящими объектами, а не странными псевдонимами для существующих значений. С числами и адресами в памяти указатели связаны только деталями реализации.
Указатель это ссылочный тип данных. Нечто, с помощью чего, можно получить доступ к другим объектам. И, в отличие от C++-ссылок, объекты-указатели являются настоящими объектами, а не странными псевдонимами для существующих значений. С числами и адресами в памяти указатели связаны только деталями реализации.
Для указателей в стандарте C++ подробно расписано, откуда они могут появляться.
Если коротко, то:
@@ -14,13 +14,13 @@
2. Как результат вызова оператора `new` (возможно, _placement new_)
3. Как результат неявного преобразования имени массива или имени функции в указатель.
4. Как результат некоторой _допустимой_ операции над другим указателем.
5. Копирование существующего указателя. В частности -- копирование `nullptr`.
5. Копирование существующего указателя. В частности копирование `nullptr`.
Все остальные источники указателей -- implementation defined или вообще undefined.
Все остальные источники указателей implementation defined или вообще undefined.
Главная операция, выполняемая над указателями, -- разыменование -- то есть получение доступа
к объекту, на который этот указатель ссылается. И вместе с этой операцией приходит главная проблема -- ее не ко всем указателям применять можно. Есть и другие операции, которые также применимы не к любому указателю.
Но, конечно, есть eдинственная операция, допустимая (почти) всегда -- сравнение на равенство (не равенство).
Главная операция, выполняемая над указателями, разыменование то есть получение доступа
к объекту, на который этот указатель ссылается. И вместе с этой операцией приходит главная проблема ее не ко всем указателям применять можно. Есть и другие операции, которые также применимы не к любому указателю.
Но, конечно, есть eдинственная операция, допустимая (почти) всегда сравнение на равенство (не равенство).
В идеальном светлом мире, от типа объекта зависит множество допустимых над ним операций. Но в случае указателей, и это очень печально, применимость или неприменимость зависит от значения указателя, но еще и от того, откуда этот указатель взялся. А также откуда взялись другие указатели!
@@ -35,10 +35,10 @@ auto x_invalid_ptr = (&x) + 2; // невалидный указатель,
```
Сравнение указателей на больше или меньше определено только для указателей на элементы одного и того же массива.
Для произвольных указателей -- unspecified.
Для произвольных указателей unspecified.
Арифметика указателей допустима только в пределах одного и того же массива (от указателя на первый элемент до указателя на элемент за последним) Иначе -- undefinded behavior.
Особый только случай `(&x) + 1` -- любой объект считается массивом из одного элемента.
Арифметика указателей допустима только в пределах одного и того же массива (от указателя на первый элемент до указателя на элемент за последним) Иначе undefinded behavior.
Особый только случай `(&x) + 1` любой объект считается массивом из одного элемента.
Пример кода, который валится с UB именно на арифметике указателей найти сложно, зато можно привести пример с итераторами (которые разворачиваются в указатели).
@@ -47,10 +47,10 @@ std::string str = "hell";
str.erase(str.begin() + 4 + 1 - 3);
```
Этот код [упадет](https://rextester.com/GPVRKM58250) в отладочной сборке под msvc. `str.begin() + 4` -- указатель на элемент за последним. И еще `+1`
Этот код [упадет](https://rextester.com/GPVRKM58250) в отладочной сборке под msvc. `str.begin() + 4` указатель на элемент за последним. И еще `+1`
выводит за пределы строки. Это UB. И не важно, что дальше вычитание возвращает внутренний указатель обратно в границы строки.
Не стоит выполнять сложные вычисления с указателями. Прибавлять к ним или вычитать лучше всегда конечный числовой результат. В данном конкретном примере рассчет отступа (4 + 1 - 3) нужно выполнить отдельно -- расставить скобки или (еще лучше) безопаснее и понятнее, вынести в отдельную переменную.
Не стоит выполнять сложные вычисления с указателями. Прибавлять к ним или вычитать лучше всегда конечный числовой результат. В данном конкретном примере рассчет отступа (4 + 1 - 3) нужно выполнить отдельно расставить скобки или (еще лучше) безопаснее и понятнее, вынести в отдельную переменную.
-----------
@@ -98,7 +98,7 @@ private:
const auto old_size = size(); // !access to invalidated data_!
data_ = ndata;
end_ = data_ + old_size;
} // else -- "ok", noop
} // else "ok", noop
}
}
```