C++ std::stringstream 到 const char* 的转换
C++ std::stringstream to const char* conversion
我正在尝试将 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
我尝试了 How to convert a std::string to const char* or char*? 中提到的所有增强功能,但没有成功。
问题是您的 const char*
指向的字符串数据在 return str;
之后已被释放。只要关联的 std::string
实例在范围内,const char*
指针将保持有效。这是假设您在此处显示的代码位于函数内。在这种情况下,字符串 tmp
将在 return str;
之后超出范围,并且将调用其析构函数,导致指向其字符数据的任何指针变为 dangling pointer.
Return 和 std::string
,然后在返回的字符串上调用 c_str()
。如前所述,只要关联的 std::string
实例在范围内,您就可以使用 const char*
指针。
您遇到的问题是,当此函数离开范围时(即当 return str;
执行时),str
指向的内存将被清理。您需要 return 一个对象来维护对数据的所有权。
//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());
}
您可以通过使用 static thread_local
存储临时对象将悬挂引用转换为非悬挂引用。
请注意,您一次只能有一个有效的 "non dangling" 参考:
#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
我正在尝试将 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
我尝试了 How to convert a std::string to const char* or char*? 中提到的所有增强功能,但没有成功。
问题是您的 const char*
指向的字符串数据在 return str;
之后已被释放。只要关联的 std::string
实例在范围内,const char*
指针将保持有效。这是假设您在此处显示的代码位于函数内。在这种情况下,字符串 tmp
将在 return str;
之后超出范围,并且将调用其析构函数,导致指向其字符数据的任何指针变为 dangling pointer.
Return 和 std::string
,然后在返回的字符串上调用 c_str()
。如前所述,只要关联的 std::string
实例在范围内,您就可以使用 const char*
指针。
您遇到的问题是,当此函数离开范围时(即当 return str;
执行时),str
指向的内存将被清理。您需要 return 一个对象来维护对数据的所有权。
//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());
}
您可以通过使用 static thread_local
存储临时对象将悬挂引用转换为非悬挂引用。
请注意,您一次只能有一个有效的 "non dangling" 参考:
#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