C++ std::带和不带\0终止符的字符串

C++ std::带和不带\0终止符的字符串,c++,C++,假设我创建了如下字符串: std::string s1 = ""; s1 += 'a'; s1 += 'b'; std::string s2 = std::string( "ab" ); 然后是这样一个: std::string s1 = ""; s1 += 'a'; s1 += 'b'; std::string s2 = std::string( "ab" ); s1和s2是否相等?创建s2时,\0是否从“ab”中剥离?如果没有,是否有一种简单(最好是一行)的方法来检查s1是否只包含且

假设我创建了如下字符串:

std::string s1 = "";
s1 += 'a';
s1 += 'b';
std::string s2 = std::string( "ab" );
然后是这样一个:

std::string s1 = "";
s1 += 'a';
s1 += 'b';
std::string s2 = std::string( "ab" );
s1
s2
是否相等?创建
s2
时,
\0
是否从
“ab”
中剥离?如果没有,是否有一种简单(最好是一行)的方法来检查
s1
是否只包含且准确地
{'a','b'}

s1和s2相等吗

创建s2时\0是否从“ab”中剥离

这不是一个真正有意义的问题。构造
s2
的代码可以根据需要进行构造。它可以复制终结者,移除它,留下它,不管它想要什么。它只需要知道如何找到C样式字符串的结尾,它确实知道

如果没有,是否有一种简单(最好是一行)的方法来检查s1是否只包含并且准确地包含{'a','b'}


string
类有一个
操作符==
,它执行您可能期望的操作,比较等价值。它了解C样式和C++样式字符串的工作方式,因此可以比较它们的值。

使用方法size()可以很容易地确定发生了什么

例如,在创建这样的对象之后

std::string s1 = "";
std::string s1( s );
s1的大小将等于0

这里称为构造函数

basic_string(const charT* s, const Allocator& a = Allocator());
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
从数组中复制字符,数组的第一个元素由s指向。由于字符串文字“”的长度等于0,因此构造的对象也没有元素,其大小等于0

在这些声明之后

s1 += 'a';
s1 += 'b';
对象将包含两个字符“a”和“b”。 因此,对象将等于像
std::string(“ab”)这样构造的对象

例如,如果有一个字符数组定义为

字符s[]={a',b','\0',c',d','\0'}

并将用于构造std::string类型的对象,如下所示

std::string s1 = "";
std::string s1( s );
那么s1将只包含两个元素“a”和“b”,其大小将等于2

考虑另一个例子是有用的。假设你写了

std::string s1 = "";
然后

s1 += 'a';
s1 += 'b';
s1 += '\0';
在这种情况下,s1将不等于object
std::string(“ab”)
,因为s1的大小现在等于3

另一个有趣的例子。您可以使用构造函数

basic_string(const charT* s, const Allocator& a = Allocator());
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
它与前面的构造函数类似,只是它允许显式指定指针s指向的字符数组中的字符数,这些字符将用于构造std::string类型的对象。 在这种情况下,如果你愿意写

std::string s1( "ab", 3 );
std::cout << s1.size() << std::endl;

if ( s1 == std::string( "ab" ) ) std::cout << "They are equal" << std::endl;
else std::cout << "They are not equal" << std::endl;
std::cout << s1 << std::endl;
同时如果你愿意写

std::string s1( "ab", 3 );
std::cout << s1.size() << std::endl;

if ( s1 == std::string( "ab" ) ) std::cout << "They are equal" << std::endl;
else std::cout << "They are not equal" << std::endl;
std::cout << s1 << std::endl;

如果您想知道
s1
s2
是否相等,您可以自己检查:
bool are_equal=s1==s2@jalf我不确定说“字符串不包含空字节”是否有意义。它的值不是,但对于C样式的字符串也是如此(可以说)。重要的是,这并不重要——C++风格的字符串是如何终止或存储它们的长度是未指定的和无关的。StackOverflow的共识似乎是,在C++11
std::string
s中,由于对
C_str
@DavidSchwartz的要求,s确实是空终止的,但是
std::string
不能如果
\0
没有意义,则null终止,对吗?否则,将
\0
插入到字符串的中间会使它变短。@cyangekko它可以nul终止,因为它的末尾可以有一个零字节。它不能以null结尾,因为您可以通过扫描nul来确定它的“真正端点”。C样式字符串也是如此--
const char*j=“a\0b;”
。您可以将其视为以nul结尾的三字节字符串,但当然不能通过扫描nul来确定其真正长度。@DevSolar它不是。我很清楚这一区别,这就是我明确提到C++11的原因。在C++98/03中,标准没有确保这一点,因为IIRC
C_str
被允许复制周围的数据。例如,检查。