【问题标题】:Concatenating string to char*将字符串连接到 char*
【发布时间】:2015-10-27 00:53:29
【问题描述】:

我是一名 C# 开发人员,当我在 C++ 中运行以下代码时,我觉得很奇怪:

std::string original = "Hello";

std::string st = original + "World";
const char *c = st.c_str();

const char *c2 = (original + "World").c_str();

std::cout << "c  = '" << c << "'" << std::endl;
std::cout << "c2 = '" << c2 << "'" << std::endl;

我得到以下输出:

c  = 'HelloWorld'
c2 = ''

在 C# 中,类似的构造将导致 cc2 具有相同的值(“Hello World”)。我的猜测是(original + "World") 的结果范围在右侧) 结束,所以c_str() 在无效输入上被调用。那是对的吗?除了创建变量来保存临时结果之外,有没有更好的方法来实现这一点?

谢谢!

【问题讨论】:

  • 问题是你有一个指向缓冲区的指针,该缓冲区在对象被销毁后失效。试试这个std::cout &lt;&lt; "c2 = '" &lt;&lt; (original + "World").c_str() &lt;&lt; "'" &lt;&lt; std::endl;
  • @VictorPolevoy:这就是未定义行为的本质。
  • @VictorPolevoy 即使您看到了并不意味着它有效的所需输出
  • 我看不出根据 C# 的功能得出 C++ 应该做什么的结论的目的。你知道他们是不同的语言,对吧?
  • 单独学习 C++ 的工作原理要比将其作为与其他语言的差异函数来学习更有建设性。

标签: c++ string scope


【解决方案1】:

我的猜测是 (original + "World") 结果的范围在右侧结束),因此 c_str() 在无效输入上被调用。对吗?

不完全是,但很接近。 c_str() 本身没问题,但是那个指针在语句结束后就失效了,所以之后使用c2 会导致 UB。

除了创建变量来保存临时结果之外,有没有更好的方法来实现这一点?

您可以将其分配给 const 引用:

const std::string &ref = original + "World";
const char *c2 = ref.c_str();

但我不认为这比创建变量更好。

【讨论】:

    【解决方案2】:

    'c2' 这里是用指向一个临时对象的指针初始化的,该对象在分号处不再存在。因此,这是未定义的行为。您需要使用中间变量:

    const auto temp(original + "World");
    const char* c2 = temp.c_str();
    

    【讨论】:

    • 附加注释:来自 C# 世界,您习惯于通过垃圾收集等方式为您管理内存。在那里您最终会引用临时对象,因此它会一直存在。在 C++ 中,您必须更加了解对象的生命周期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    相关资源
    最近更新 更多