[C++] Как вым добавочка к интерфейсу string'а?
В stl-ном стринге это делается методом c_str
c_str дает константную строку
Пусть будет так:
const char *operatorvoid);
Если это эквивалентно c_str, то лучше не надо. Имхо, ухудшается читабельность кода.
![](/images/graemlins/smile.gif)
К тому же, вызванная функция должна освободить память из-под строки - если она все же дублируется. Это неочевидно из записи str и, к тому же, не всегда желательно.
Вызвавшая?
По существу: втопку. Пусть лучше у стринга оператор форматирует жосский диск, или печатает "ХУЙ"!
>вызваннаяЕсли я правильно понял, предлагается использовать этот оператор для передачи строки как const char*, то есть
Вызвавшая?
void f(const char*);
std::string s;
f(s;
Тогда освободить память может только вызванная функция.
Короче, идея автора треда - отстой.
Есть ещё одна проблема: кто будет освобождать память, выделенную твоим оператором преобразования строки в char*? Строка? Или ты? Если строка, то ты не сможешь менять размер строки, на которую указывает этого char*. Если ты — то будут утечки памяти. Как показал опыт, в случаях, когда память выделяется функцией, а освобождаться должна вызываемой стороной, вызывающая сторона обычно забывает освободить память. Далее, память должна быть освобождена парным способом, к способу аллокации. Какой способ аллокации у std::string? Тебя это сильно удивит, но не new[] и не malloc. Поэтому, удаление этой памяти через delete/delete[]/free/realloc будет заведомо некорректным. Может быть помещать результат в статической памяти? Тогда программа будет заведомо не thread-safe, а строки в char* можно будет кастовать только если их размер не превышает размера статического буфера. Последнее не исправляется даже за счёт thread-specific storage (__thread, если твой компилятор, линкер и среда запуска приложений поддерживают такое).
string - это не интерфейс
В дополнение к Serezhе
string s1,s2;
....
s1+s2 — конкатенация
// очепятка:
s1-s2 — разность адресов, проблемы с памятью.
Этот вопрос обсуждаетсяв книге у Саттера. Могу посмотреть точную ссылку, но суть уже изложили тут.
Компилятор не будет знать, какой из конструкторов использовать std::string(const std::string &) или std::string (const char * const) при конструировании строки по одному строковому аргументу.
Да, пожалуй самый существенный аргумент. Кроет всё.
![](/images/graemlins/blush.gif)
Ничего подобного не добавили в стандарт потому, что строки будут без дополнительных указаний сами кастоваться в char*. Это плохо по двум причинам — во-первых повышает неоднозначность перегрузки. Компилятор не будет знать, какой из конструкторов использовать std::string(const std::string &) или std::string (const char * const) при конструировании строки по одному строковому аргументу. Аналогично для других операций, которые перегружены для std::string и char *.хм
впервые вижу гонево вашего авторства
1. Какое отношение перегрузка оператора скобочки имеет к неявному преобразованию типов? Преобразование типов определяется либо конструкторами, либо определением оператора с названием типа, в который происходит преобразование
foo_class::operator foo_type;
а это:
foo_class::operator...)
здесь не причем.
2. Даже если определить преобразование типа std::string в const char*, все равно никакой неоднозначности при вызове
std::string s;
foo(s);
при наличии функций
foo(const char* const)
foo(const std::string&)
не будет.
Ботайте правила разрешения таких неоднозначностей (преобразование в ссылку или в константу более приоритетно чем любое другое неявное преобразование).
Впрочем то, что определять такое неявное преобразование как std::string в const char* - очень плохая идея, это несомненно по многим причинам, включая изложенные вами.
Какой способ аллокации у std::string? Тебя это сильно удивит, но не new[] и не malloc. Поэтому, удаление этой памяти через delete/delete[]/free/realloc будет заведомо некорректным.
способ аллокации std::string - это std::allocator<char>
который реализован именно через new/delete
но конечно в любом случае возвращать из функции динамически выделенную память, которую должен освобождать пользователь - неприемлемо для стандартной библиотеки (и очень плохая идея для любой другой библиотеки)
к остальному +1
Мой предыдущий пост касается приведения типов.
Оператор круглые скобки имеет сделан для того, чтобы объекты вели себя подобно функциям. Преобразование в char* — это не тот случай. Так что предложение не соответствует концепции оператора . Читаемость кода ухудшается, потому как из кода неясно, что этот оператор возвращает. Лучше дописать c_str.
Комментарии про выделение/освобождение памяти не рулят, потому как они настолько же применимы и к c_str
Оператор круглые скобки имеет сделан для того, чтобы
Ниасилил твой русский язык.
Комментарии про выделение/освобождение памяти не рулят, потому как они настолько же применимы и к c_strОшибаешься. c_str не выделяет новую память, и вызывающая функция не должна ничего освобождать.
Попробуй такой код:
std::string s("111");
const char *c = s.c_str;
printf("s = %s\n", s.c_str;
printf("c = %s\n", c);
s.append("22");
printf("s = %s\n", s.c_str;
printf("c = %s\n", c);
c указывает на то же место, что и s. Никаких проблем с памятью.
+1
Согласен, я затупил
Оператор круглые скобки сделан для того, чтобы объекты вели себя подобно функциям. Преобразование в char* — это не тот случай. Так что предложение не соответствует концепции оператора . Читаемость кода ухудшается, потому как из кода неясно, что этот оператор возвращает.+1
именно так
хмСогласен. Но, насколько я понял, в первом посте треда имел в виду именно оператор неявного приведения типа. По крайней мере его слова
впервые вижу гонево вашего авторства
1. Какое отношение перегрузка оператора скобочки имеет к неявному преобразованию типов? Преобразование типов определяется либо конструкторами, либо определением оператора с названием типа, в который происходит преобразование
code:operator foo_type;
а это:
code:operator...)
здесь не причем.
А вот зато стринг сможешь как параметр chost char* передавать.
(в одном из следующих постов) наводят на такие мысли.
2. Даже если определить преобразование типа std::string в const char*, все равно никакой неоднозначности при вызове
code:
std::string s;
foo(s);
при наличии функций
code:
foo(const char* const)
foo(const std::string&)
не будет.
Ботайте правила разрешения таких неоднозначностей (преобразование в ссылку или в константу более приоритетно чем любое другое неявное преобразование).
Возможно, я не достаточно хорошо знаю стандарт. Но у меня возникали проблемы с неоднозначностью перегрузки именно когда класс А имел конструктор от типа B и оператор преобразования в этот тип B. Неоднозначности возникали при попытке разрешить смешанные операции +, -, ... Возможно с тех пор стандарт поменяли, компилятор исправили, ...
Какой способ аллокации у std::string? Тебя это сильно удивит, но не new[] и не malloc. Поэтому, удаление этой памяти через delete/delete[]/free/realloc будет заведомо некорректным.code:способ аллокации std::string - это std::allocator<char>
который реализован именно через new/delete
Память, выделенную через аллокатор и освобождать надо через аллокатор. И не в коем случае, не через delete. Вне зависимости от того как написан аллокатор и специфицирована ли его реализация стандартом.
Ошибаешься. c_str не выделяет новую память, и вызывающая функция не должна ничего освобождать.Ошибаешься ты. Стандарт не запрещает c_str как и data выделять память, но требует от пользователя не менять память и не использовать её после того, как сама строка удалена или для неё вызван не-константный метод. Это позволяет реализовать c_str/data как с выделением памяти (например, если строка может хранить своё содержимое не последовательно в памяти, как rope; или, например, если строки реализованы с отложенным копированием copy-on-write так и без него. Единственно что — если строка выделяет память, то она же её и освободит.
если строка выделяет память, то она же её и освободитНу да, ключевая половина в моём предложении - вторая.
Оставить комментарий
Werdna
Эта штука делает дубликат строки и возвращает указатель на него.
Возник спор — это хорошо или плохо?