1

学习 C++。我只想获取字符串中的第一个字符,然后根据该字符创建一个新字符串,然后将其打印出来:

#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
    string name = "Jerry";
    char firstCharacter = name.at(0);
    string stringOfFirstCharacter = string(&firstCharacter);
    cout << stringOfFirstCharacter;
    return 0;
}

输出是:

J
Jerry

我真的不知道为什么它也在打印Jerry。这是为什么?

4

4 回答 4

8

您的代码具有未定义的行为。接受指针的构造函数的签名char要求它是一个指向空终止字符串的指针,在您的情况下它不是,因为它是单个字符。

我的猜测是您的实现使用了小对象优化,并且“Jerry”足够小,可以存储在std::string对象内部而不是动态分配。堆栈中两个对象的布局恰好是先firstCharacter,后name。当您调用std::string(&firstCharacter)它时,它会读取直到它遇到第一个空字符(在std::string缓冲区内)并停在那里。

于 2013-04-17T20:17:51.677 回答
3

您正在从 a 构造一个std::string对象char*(因为您正在获取 的地址firstCharacter)。的构造函数不会将指向字符的指针解释为字符本身std::string,而是将其解释为以 null 结尾的字符串。

在这种情况下,您的程序具有Undefined Behavior,因为 的地址firstCharacter不是以空字符结尾的字符串的第一个字符的地址。

你应该做的是:

string stringOfFirstCharacter(1, firstCharacter);
cout << stringOfFirstCharacter;

如果你真的想创建一个单字符的字符串。但是,请注意,为了将字符打印到标准输出,您可以简单地编写:

cout << firstCharacter;

甚至:

cout << name.at(0);
于 2013-04-17T20:17:42.613 回答
2

使用string(&firstCharacter),您正在使用表单的std::string构造函数

std::string( const char* s, const Allocator& alloc = Allocator() );

这种形式需要一个指向以null 结尾的字符数组的指针。将指针传递给非空终止字符是不正确的。

如果您打算使用 1 初始化字符串char,则应使用以下形式:

string( 1, firstCharacter )
于 2013-04-17T20:17:23.997 回答
1

string您正在使用的构造函数(带char *参数的构造函数)旨在将 C 样式的字符串转换为 C++ 字符串对象 - 而不是单个字符。通过将单个字符传递给它,您会导致未定义的行为。

在您的特定情况下, 之后的内存中似乎没有零字节firstCharacter,因此构造函数贯穿并包含所有name内容!

于 2013-04-17T20:17:39.577 回答