вызов метода c_str() глобального объекта string
От: Аноним  
Дата: 28.02.13 13:33
Оценка: 1 (1)
Здравствуйте, форумчане. Легален ли такой код?

const std::string g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";

const char *get_str() {
    return g_str.c_str();
}
Re: вызов метода c_str() глобального объекта string
От: adevelgio Россия  
Дата: 28.02.13 14:09
Оценка:
Пока внутреннее состояние объекта g_str не изменится адрес возвращенный c_str() будет валиден.
Re[2]: вызов метода c_str() глобального объекта string
От: Erop Россия  
Дата: 28.02.13 14:18
Оценка:
Здравствуйте, adevelgio, Вы писали:

A>Пока внутреннее состояние объекта g_str не изменится адрес возвращенный c_str() будет валиден.


Дык const жеж...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: вызов метода c_str() глобального объекта string
От: Erop Россия  
Дата: 28.02.13 14:20
Оценка: +4
Здравствуйте, Аноним, Вы писали:

А>
А>const std::string g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";

А>const char *get_str() {
А>    return g_str.c_str();
А>}
А>


В целом вот именно такой почти легален. Проблема состоит в том, что get_str() могут позвать когда g_str уже или ещё не существует...

но ты чего-то нам не договариваешь... Зачем это надо делать настолько стоя и в гамаке?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: вызов метода c_str() глобального объекта string
От: adevelgio Россия  
Дата: 28.02.13 14:31
Оценка: -2
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, adevelgio, Вы писали:


A>>Пока внутреннее состояние объекта g_str не изменится адрес возвращенный c_str() будет валиден.


E>Дык const жеж...


const не остановит жажду к извращениям

const std::string g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";

int main()
{
  char const * ptr = g_str.c_str();
 
  std::string * s = const_cast<std::string*>(&g_str);
  *s += "a";

  printf("%s\n", g_str.c_str());
  return 0;
}
Re[4]: вызов метода c_str() глобального объекта string
От: Erop Россия  
Дата: 28.02.13 14:46
Оценка: +2 :))) :)
Здравствуйте, adevelgio, Вы писали:

A>const не остановит жажду к извращениям


A>
A>const std::string g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";

A>int main()
A>{
 
A>  std::string * s = const_cast<std::string*>(&g_str);
A>  *s += "a";
A>}
A>


Это не только УГ, но ещё и UB...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: вызов метода c_str() глобального объекта string
От: rg45 СССР  
Дата: 28.02.13 15:10
Оценка: 4 (2)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, форумчане. Легален ли такой код?


А>
А>const std::string g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";

А>const char *get_str() {
А>    return g_str.c_str();
А>}
А>


Если только обращение к get_str не выпоняется из конструкторов/деструкторов других статических объектов, то все в порядке. Но, вообще говоря, глобальные константы нетривиальных типов чреваты неприятностями.

Первая неприятность та, что константы по умолчанию имеют внутреннее связывание, это означает, что при включении заголовочного файла с такой константой в несколько единиц трансляции, то каждый из них будет содержать свой собственный экземпляр такой константы, скорее всего (зависит от реализации) содержимое строки также будет растиражировано и приведет к лишнему расходу памяти.

Но предыдущая проблема — ерунда по сравнению с сюрпризами, которые может преподносить неопределенность порядка инициализации объектов со статическим временем жизни, определенных в разных единицах трансляции. Предположим пользователь определил какой-то собственный класс, который в своем конструкторе обращается к какой-то глобальной константе, например, к такой вот строке. Теперь если пользователь захочет помимо строковой константы, определить также константу своего типа (а почему бы нет?), его могут ожидать те самые сюрпризы. Допустим, у него есть один общий заголовочный файл, в котором определен его класс и обе константы и два cpp файла — в одном реализация класса, в другом — все остальное (функция main):

Foo.h

class Foo
{
public:
  Foo();
  // . . .
};

const std::string g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";
const Foo g_foo;

Foo.cpp
#include<Foo.h>

Foo::Foo()
{
  // Some use of the g_str constant from Foo.h
  std::cout << g_str << std::endl;
}

main.cpp
#include<Foo.h>

int main()
{
  // Some use of the g_str constant from Foo.h
  g_foo.do_something();
}


И вот теперь мы имеем в каждом из cpp файлов по паре отдельных констант g_str и g_foo, только какая из двух пар будет проинициализарована сначала, а какая потом мы не знаем, порядок может быть любым. А что если первыми проинициализируются константы из main.cpp? А в этом случае при инициализации g_foo будет вызван конструктор Foo::Foo, определенный в Foo.h, который сразу же использует еще не определенную константу g_str из своего модуля! Об этом надо знать и помнить.

А как насчет заменить std::string обычным const char*? В этом случае озвученные неприятности сразу отпадают.
const char* g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: вызов метода c_str() глобального объекта string
От: Mr.Delphist  
Дата: 04.03.13 12:58
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, форумчане. Легален ли такой код?


А>
А>const std::string g_str = "1234567890-abcdefghijklmnopqrstuvwxyz";

А>const char *get_str() {
А>    return g_str.c_str();
А>}
А>


В общем случае такого лучше избегать. Поскольку c_str() может отдавать временный буфер, то запоминать адрес на него где-то снаружи — недальновидно. Да, сейчас оно работает, но лёгким движением руки мы убираем const из g_str, затем ещё пара индо-патчей, и всё, бомба затикала. Компилятор не предупредит.

Безопасней держать в голове условие, что буфер c_str() живёт как временный объект, до ближайшей точки с запятой. Тогда волей-неволей будешь оперировать с константной ссылкой на g_str чем с сырым указателем.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.