std::string和std::u16string(或u32string)之间的区别

3
我在提问之前参考了以下文章: std::string,wstring,u16/32string澄清
std::u16string、std::u32string、std::string、length()、size()、codepoints和字符 但它们没有回答我的问题。看下面的简单代码:
#include<iostream>
#include<string>
using namespace std;

int main ()
{
  char16_t x[] = { 'a', 'b', 'c', 0 };
  u16string arr = x;

  cout << "arr.length = " << arr.length() << endl;
  for(auto i : arr)
    cout << i << "\n";
}

输出为:
arr.length = 3  // a + b + c
97
98
99

鉴于 std::u16stringchar16_t 而不是 char 组成,输出应该是:
arr.length = 2  // ab + c(\0)
<combining 'a' and 'b'>
99

请原谅我这个初学者的问题。我的要求是要清晰地了解新的C++11字符串概念。
编辑:
从@Jonathan的答案中,我得到了问题的漏洞。我的意思是如何初始化char16_t,使得arr的长度变为2(即ab,c\0)。 FYI,以下结果不同:
  char x[] = { 'a', 'b', 'c', 0 };
  u16string arr = (char16_t*)x;  // probably undefined behavior

输出:

arr.length = 3
25185
99
32767

你有一个 char16_t 元素的 array。你用 3 个元素初始化它... - HvS
@JonathanWakely,确实是这样,我的打字和思考之间有点冲突:)。重点是 - 用“fixed”数量的元素初始化。 - HvS
3
为什么要踩这个帖子?虽然它并不是特别令人兴奋,但提到的陷阱确实值得注意。 - Solkar
4个回答

4
不,您已经创建了一个由四个元素组成的数组,第一个元素是转换为char16_t'a',第二个元素是转换为char16_t'b'等。
然后,您从该数组(转换为指针)创建了一个u16string,它会读取每个元素直到空终止符。

3
当你执行以下操作时:
char16_t x[] = { 'a', 'b', 'c', 0 };

与此类似(不考虑字节序):

char x[] = { '\0', 'a', '\0', 'b', '\0', 'c', '\0', '\0' };

每个字符在内存中占据两个字节
因此,当您请求的长度时,每两个字节被计算为一个字符。毕竟,它们是两个字节(16位)字符。 编辑: 您的额外问题是创建一个没有空终止符的字符串。
尝试这个:
char x[] = { 'a', 'b', 'c', 0 , 0, 0};
u16string arr = (char16_t*)x;

现在第一个字符是{'a', 'b'},第二个字符是{'c', 0},并且您还有一个空终止符字符{0, 0}


1

输出结果应该是:

arr.length = 2
// ab + c(\0) 99

不是这样的。 x 的元素是 char16_t 类型的,无论你提供什么类型的字符字面量进行初始化:

#include<iostream>

int main () {
    char16_t x[] = { 'a', 'b', 'c', 0 };
    std::cout << sizeof(x[0]) << std::endl;
}

输出:

2 

实时示例

补充指问题的编辑

我不推荐将终止符从字符串中拆分出来。 ;)

#include<iostream>
#include<string>

int main () {
    char x[] = { 'a', 'b', 'c', 0, 0, 0, 0, 0};

    std::wstring   ws   = reinterpret_cast<wchar_t*>(x);
    std::u16string u16s = reinterpret_cast<char16_t*>(x);

    std::cout << "sizeof(wchar_t):  "       << sizeof(wchar_t)
              << "\twide string length: "   << ws.length()   
              << std::endl;

    std::cout << "sizeof(char16_t): "       << sizeof(char16_t)
               << "\tu16string length:  "   << u16s.length()   
               << std::endl;
}

实时示例

输出(使用g++编译)

sizeof(wchar_t):  4 wide string length: 1
sizeof(char16_t): 2 u16string length:   2

如预期一样,不是吗。

我认为你用一个例子解决了问题!谢谢。你能看一下编辑后的问题吗? - iammilind

-1
C++支持以下方式从8位整数构建16位整数:
char16_t ab = (static_cast<unsigned char>('a') << 8) | 'b';
// (Note: cast to unsigned meant to prevent overflows)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接