четверг, 8 апреля 2021 г.

[prog.c++.bicycle] Отдельный тип для строковых литералов своими руками

Если я правильно понимаю, то в C и C++ строковые литералы хранятся в статической памяти. Поэтому указатель на строковый литерал остается валидным, фактически, до самого конца работы программы. Т.е. если мы пишем что-то вроде:

class long_living_object {
  const char * value_;
public:
  long_living_object(const char * v) : value_{v} {}
  ...
};

long_living_object make_object_ok() {
  return { "Hello, World!" };
}

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

К сожалению, в C++ нет никакого способа отличить указатель на строковый литерал от указателя на какой-то временный массив символов. Т.е., ничто в языке не запрещает нам сделать так:

long_living_object make_object_bug() {
  char greeting[] = "Hello, World!";
  return { greeting };
}

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

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

понедельник, 5 апреля 2021 г.

[life.music] Продолжение саги о выборе хороших, но недорогих наушников на Aliexpress. Отчет о побывавших у меня внутриканалках

Сегодня кратко пройдусь по моделям внутриканальных наушников, которые побывали у меня в руках. За исключением KZ ZSN Pro, с которых все началось и которые я благополучно продал еще в январе.

Прежде чем начать...

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