【问题标题】:Difference between std::string and std::u16string (or u32string)std::string 和 std::u16string(或 u32string)之间的区别
【发布时间】:2014-09-17 02:07:29
【问题描述】:

在这里提问之前我已经参考了以下帖子:

std::string, wstring, u16/32string clarification
std::u16string, std::u32string, std::string, length(), size(), codepoints and characters

但他们不是我的问题。看下面的简单代码:

#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(即abc\0)。
仅供参考,下面给出了不同的结果:

  char x[] = { 'a', 'b', 'c', 0 };
  u16string arr = (char16_t*)x;  // probably undefined behavior

输出:

arr.length = 3
25185
99
32767

【问题讨论】:

  • 您有一个 arraychar16_t 元素。你用3 元素初始化它...
  • @JonathanWakely,是的,确实,我的打字和我的想法有点冲突:)。点正在 - 使用 fixed 数量的元素进行初始化。
  • +1 @downvoters:为什么要否决这个?这并不令人兴奋,但这是一个值得一提的陷阱。

标签: c++ string c++11 output


【解决方案1】:

不,您创建了一个包含四个元素的数组,第一个元素是'a' 转换为char16_t,第二个元素是'b' 转换为char16_t 等等。

然后,您从该数组创建一个u16string(转换为指针),它会读取每个元素直到空终止符。

【讨论】:

    【解决方案2】:

    当你这样做时:

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

    类似于这样做(不支持字节顺序):

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

    每个字符在内存中占用 两个字节

    因此,当您询问 u16string 的长度时,每个 两个 字节都被计为 一个 字符。毕竟,它们是两字节(16 位)字符。

    编辑:

    您的另一个问题是创建一个 没有空终止符的字符串。

    试试这个:

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

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

    【讨论】:

      【解决方案3】:

      输出不应该是:

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

      没有。 x 的元素是 char16_t,不管你为初始化提供了 char 字面量:

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

      输出:

      2 
      

      Live example

      附录指问题的编辑

      我不完全建议将终止从字符串中移除。 ;)

      #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;
      }
      

      Live example

      输出(用 g++ 编译)

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

      正如预期的那样,不是吗。

      【讨论】:

      • 我想你已经用一个例子搞定了!谢谢。你能看看编辑过的问题吗?
      【解决方案4】:

      C++ 支持以下方式从 8 位整数构建 16 位整数:

      char16_t ab = (static_cast<unsigned char>('a') << 8) | 'b';
      // (Note: cast to unsigned meant to prevent overflows)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-28
        • 2015-01-07
        • 1970-01-01
        • 2014-03-04
        • 2013-01-18
        • 2012-04-25
        • 2015-07-21
        • 2012-10-27
        相关资源
        最近更新 更多