Изменение данных без учета квалификатора const

StackOverflow https://stackoverflow.com//questions/24029777

  •  21-12-2019
  •  | 
  •  

Вопрос

Ранее я уже задавал соответствующий вопрос по этому поводу, поэтому знаю, что это неопределенное поведение.

возврат const char* в char* и последующее изменение данных

string _str = "SDFDFSD";
char* pStr = (char*)_str.data();
for (int i = 0; i < iSize; i++)
    pStr[i] = ::tolower(pStr[i]);

У меня была дискуссия по этому поводу с одним из моих коллег.И он сказал мне, что в этом сценарии никаких проблем не возникнет, если я не изменю длину данных.Если я изменю данные, но оставлю такую ​​же длину, это никогда не создаст никаких проблем, поскольку нет возможности std::string чтобы обнаружить, что данные были изменены.Это не вызовет никаких внутренних противоречий ни в _str.Так ли это на самом деле?

Это было полезно?

Решение

Неопределенное поведение Боюсь, его слишком сильно порицали, а упоминания о носовых демонах, похоже, убедили большинство людей в том, что это скорее миф, чем что-либо еще.

Похоже, ваш коллега настолько десенсибилизировал, что для того, чтобы вас убедить, необходимо привести ему конкретные доказательства сути вопроса.К счастью, если у вас есть gcc, это можно сделать:

#include <iostream>
#include <string>

int main() {
    std::string const UPPER = "HELLO, WORLD!";
    std::cout << "UPPER: " << UPPER << "\n";

    std::string lower = UPPER;
    for (char* begin = const_cast<char*>(lower.data()),
         * end = begin + lower.size();
         begin != end;
         ++begin)
    {
        *begin = std::tolower(*begin);
    }
    std::cout << "lower: " << lower << "\n";
    std::cout << "UPPER: " << UPPER << "\n";
    return 0;
}

Если вы используете gcc, вот что ты получишь:

UPPER: HELLO, WORLD!
lower: hello, world!
UPPER: hello, world!   // What the hell ? UPPER was const !!!

Почему ?Поскольку gcc исторически использовал Копирование при записи, и поскольку ты обманул он не обнаружил запись, и поэтому базовый массив хранения является общим.

Примечание:да, это несовместимо с C++11, но мне бы хотелось поработать на C++11.

Другие советы

В соответствии с данные() документация:

Изменение массива символов, доступ к которому осуществляется через данные, является неопределенным поведением.

Значит, ваш коллега не прав, подвоха нет, это неопределенное поведение.То, что происходит, зависит от реализации.

Плохая идея!Вы не можете знать наверняка, как строка реализована на какой-либо текущей или будущей платформе.Например, это может быть совместное использование хранилища с другими объектами, которые чем-то похожи.На некоторых платформах данные могут помещаться в сегмент только для чтения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top