Верен ли следующий код?
constexpr char s[] = "a, bb, ccc";
static const char * s1 = s;
char * s2 = const_cast<char *>(s1);
s2[5] = 'x';
Моя первая идея заключалась в том, что 's' существует только во время компиляции, а 's1', вероятно, является какой-то копией 's', но, вероятно, это не совсем правильно, потому что строка 2 не компилируется без 'const':
static char * s1 = s;
Ошибка с MSCV2017: «инициализация»: невозможно преобразовать «const char [11]» в «char [11]».
поэтому непонятно, какая связь между «s» и «s1»? Ссылаются ли они на один и тот же строковый литерал?
Определение
static const char * s1 = s;
равно
static const char * s1 = &s[0];
То есть вы заставляете s1
указывать на первый элемент s
, вот и все. Никакой "копии" не делается.
Вот почему вы не можете использовать указатели на неконстантные (т.е. char *
), поскольку s1
будет указывать на постоянные данные.
И именно поэтому s2[5] = 'x'
приведет к неопределенное поведение, когда вы попытаетесь изменить постоянные данные.
приводит ли этот код к неопределенному поведению: {const int a = 1; const_cast<int *>(&a) = 5;} ?
@AlexeyStarinsky Даже не компилируется error: lvalue required as left operand of assignment
@Tetix OP пропустил разыменование или OP мог использовать ссылку напрямую, но дело в том, что вы не можете изменить a
.
@Tetix Я имею в виду {const int a = 1; *(const_cast<int *>(&a)) = 5;}
@AlexeyStarinsky Да, это UB. Любая попытка изменить постоянные данные приводит к UB.
@Acorn, для чего нужен const_cast?
@Someprogrammerdude, для чего нужен const_cast?
@AlexeyStarinsky Любое использование const_cast
должно быть красным флагом, что происходит что-то плохое. Как и старые слепки в стиле C.
@AlexeyStarinsky Вы не можете отбрасывать const
, используя другие примитивы приведения C++, только используя const_cast
. Но, как я сказал выше, не делайте этого.
@alexey, если у вас есть указатель на const или ссылка на const, а также вы знаете, что данные на самом деле не являются константами, приведение const позволяет безопасно их отбрасывать. Если вы ошибаетесь, это УБ. Вы также можете добавить const с помощью const cast.
my first idea was that 's' exists only at compile time
Нет, он также существует во время выполнения. constexpr
не означает «только во время компиляции». Здесь это означает, что «s
должен быть инициализирован константным выражением» (по сути, константой времени компиляции), что означает, что его можно использовать и в константных выражениях.
's1' probably is some kind of a copy of 's'
s1
просто указывает на первый символ массива s
. Это не копия содержимого массива.
line 2 does not compile without 'const':
Вы не можете сделать это без const_cast
-- но в любом случае вам это не нужно, потому что изменение исходной const
переменной (которой является s
) является неопределенным поведением.
Обратите внимание, что тег
c++17
относится к C++17 стандартный, а не к MSVC2017 (это будет тегvisual-studio-2017
).