C++ std::stringstream для преобразования в const char*
Я пытаюсь преобразовать stringstream
в const char*
, но я всегда получаю пустую строку.
Мой код:
#include<string>
#include<sstream>
#include<stdio.h>
const char* test(std::string city, std::string street, int houseNumber, int postCode) {
std::stringstream ss;
ss << city << " " << street << " " << houseNumber << " " << postCode;
const std::string tmp = std::string{ss.str()};
const char* str = tmp.c_str();
return str;
}
int main(){
printf(test("demo", "Demo", 1, 1234));
}
Ожидаемый результат: demo Demo 1 1234
Я перепробовал все улучшения, упомянутые в разделе Как преобразовать std::string в const char* или char *?, но у меня не было успеха.
3 ответа
Проблема в том, что данные строки вашего const char*
указывает на был освобожден после return str;
, const char*
указатель будет оставаться в силе до тех пор, пока связанный std::string
экземпляр находится в пределах видимости. Это при условии, что код, который вы показали здесь, находится внутри функции. В этом случае строка tmp
выйдет за рамки после return str;
, и вызывается его деструктор, в результате чего любой указатель, указывающий на его символьные данные, становится висящим указателем.
Вернуть std::string
вместо этого и позвоните c_str()
вместо возвращаемой строки. Как уже упоминалось, вы можете использовать const char*
указатель до тех пор, пока связанный std::string
экземпляр находится в пределах видимости.
Вы можете превратить висячие ссылки в не висячие ссылки с помощью static thread_local
хранить временный объект.
Обратите внимание, что за один раз вы сможете иметь только одну активную "не висящую" ссылку:
#include <string>
#include <sstream>
#include <iostream>
const char* to_cstr(std::string && s)
{
static thread_local std::string sloc;
sloc = std::move(s);
return sloc.c_str();
}
const char* make_address(std::string const& city,
std::string const& street,
std::string const& houseNumber,
std::string const& postCode)
{
std::stringstream ss;
ss << city << " " << street << " " << houseNumber << " " << postCode;
return to_cstr(std::move(ss).str());
}
int main()
{
const char* p = make_address("London","Bob Street","42","W1ABC");
std::cout << p << std::endl;
}
ожидаемый результат:
London Bob Street 42 W1ABC
Проблема, с которой вы сталкиваетесь, заключается в том, что когда эта функция выходит из области видимости (т.е. когда return str;
выполняет), память str
указывает на то, что будет очищен. Вам необходимо вернуть объект, который будет поддерживать владение данными.
//std::string_view is >=c++17, use std::string const& for older compilers
std::string get_formatted_address(
std::string_view city,
std::string_view street,
std::string_view houseNumber,
std::string_view postCode
) {
std::stringstream ss;
ss << city << " " << street << " " << houseNumber << " " << postCode;
return ss.str();
}
int main() {
auto city = "New York", street = "Rockefeller Lane", houseNumber = "1234", postcode = "56789";
auto formatted_address = get_formatted_address(city, street, houseNumber, postcode);
//Here, formatted_address holds ownership over the memory, so calling c_str is safe
printf("Address: %s\n", formatted_address.c_str());
}