【问题标题】:Converting std::string to const char*, getting errors将 std::string 转换为 const char*,出现错误
【发布时间】:2014-01-09 19:07:40
【问题描述】:
#include <iostream>
#include <sstream>

template <typename T>
const char* numberToString(T number) {
    std::ostringstream ss;
    ss << number;
    return ss.c_str();
}

int main() {
    printf(numberToString(123));
    return 0;
}

我的错误:

1>d:\programming\euler\problem 4\problem 4\problem 4\source.cpp(8): error C2039: 'c_str' : is not a member of 'std::basic_ostringstream<char,std::char_traits<char>,std::allocator<char>>'
1>          d:\programming\euler\problem 4\problem 4\problem 4\source.cpp(26) : see reference to function template instantiation 'const char *numberToString<int>(T)' being compiled
1>          with
1>          [
1>              T=int
1>          ]

为什么这不起作用?

【问题讨论】:

  • 您无法从临时字符串中获取 const char* ( c_str() )。从 numberToString 返回后,您的 stringstream 将被销毁,其底层 std::string 也将被销毁。当您调用c_str() 时,它将返回一个指向仅在std::string 生命周期内有效的指针。我建议使用std::string,因为它是一个对象(不是指针),它会在需要时被复制。
  • 仅供参考,标准库提供了此功能,无需为它编写函数。 en.cppreference.com/w/cpp/string/basic_string/to_string
  • 你读过文档,嘿? ...

标签: c++ string types


【解决方案1】:

你想做的:

template <typename T>
std::string numberToString(T number) {
    std::ostringstream ss;
    ss << number;
    return ss.str();
}

int main() {
    std::cout << numberToString(123);
    return 0;
}

std::ostringstream 中获取底层std::string,然后在std::string 中得到c 样式字符串。正如其他人所指出的,c_str 返回的指针超出范围,因此您必须将其复制到缓冲区或另一个 std::string。如果你坚持使用printf,那么在函数调用上使用c_str

printf("%s", numberToString(123).c_str());

欲了解更多信息,请参阅Is it a good idea to return " const char * " from a function?

取决于 somestlstring 是什么以及那里正在做什么。

如果它是一个局部变量,你将返回一个指向内存的指针 GetSomeString 完成时正在释放,所以它是一个悬空 指针和错误。

这一切都归结为 somestlstring 的生命周期和操作 你执行它。 .c_str() 返回的指针保证 仅在字符串中的下一个变异操作之前有效。因此,如果 从调用 .c_str() 到 s 之前,有些东西会改变 somestlstring 构建后,您将处于未定义的行为领域。

但是,您可以简单地使用std::to_string

std::string s = std::to_string(123);

【讨论】:

  • 我这样做了,但现在我的程序没有输出任何东西。怎么了?
  • 你为什么需要temp?继续return ss.str()。或者至少做temp = ss.str()。您浪费时间创建string,获取其内部缓冲区并构造另一个string
【解决方案2】:

这是因为c_str()std::string 的成员函数,它返回一个const char*

要获取字符串流的底层字符串,您必须使用str()

这个错误几乎是不言自明的:

错误 C2039:“c_str”:不是“std::basic_ostringstream”的成员

但是请注意,您返回的指针(由str() 返回的临时字符串的基础数据)在 return 语句之后(即在调用代码中)将不存在,并且操作该指针将完全Sureley 最终会出现未定义的行为。

由于您在 C++ 中,您可以直接返回 std::string,并使用

输出它
std::cout << numberToString(123);

这样会更安全。

【讨论】:

  • 它不会是指向流内部数据的指针,str() 返回流中包含的字符串的副本。无论如何,它仍然是指向将在该表达式末尾销毁的临时指针。
  • @Praetorian 对!已更正。
【解决方案3】:

c_str() 不存在 std::ostringstream。你的意思是:

template <typename T>
const char* numberToString(T number) 
{
    std::ostringstream ss;
    ss << number;
    return ss.str().c_str();
}

进行更改后,您将遇到另一个问题:您将返回一个指向刚刚销毁的缓冲区的指针。要解决这个问题,您应该返回 std::string:

template <typename T>
std::string numberToString(T number) 
{
    std::ostringstream ss;
    ss << number;
    return ss.str();
}

std::to_string 已经可以做到这一点,所以编写自己的函数真的没有意义。

【讨论】:

  • 如果你没有 C++11 编译器也不是没有意义,而且很多人没有。但是,对于拥有 c++11 编译器的人来说,这是一个不错的建议。
  • @shawn1874 很公平……不过,在这一点上,所有旧的编译器都应该很快被淘汰。见鬼,C++14 正处于获批的最后阶段。
【解决方案4】:

c_strstd::string 的成员,而不是ostringstream。如果您想从流中获取string,请使用str()。但是请注意,从 string 返回 const char* 是错误的 - 在您可以使用 const char* 之前,string 将超出范围。因此,让你的函数返回一个string(或者让它获得一个要写入的缓冲区):

template <typename T>
std::string numberToString(T number) {
    std::ostringstream ss;
    ss << number;
    return ss.str();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 2011-05-11
    • 2016-09-12
    • 2018-08-23
    相关资源
    最近更新 更多