从C字符串构造std::string与从另一个std::string构造std::string时存在不一致性

3
为什么std::string构造函数仅依据其所构造的字符串类型不同而产生不同的输出结果?
例如,考虑以下C++代码:
#include <iostream>
#include <string>

int main() {
    char cstyle[] = "01234567";
    std::string std = "01234567";
    std::cout << std::string(cstyle, 4) << std::endl;
    std::cout << std::string(std, 4) << std::endl;
    return 0;
}

产生以下输出:
0123
4567

我期望它们两个都产生`0123`,或者都产生`4567`,但我不希望一个产生`0123`而另一个产生`4567`。
为什么会出现这种不一致性?
编辑:这个问题不是关于调用哪个默认构造函数,或者它们是否执行不同的操作。它们确实执行了不同的操作,并且调用了不同的构造函数。这个问题是关于为什么它们不做相同的事情。换句话说,这更像是一个哲学问题而不是技术问题。

2
std::string在C++标准化之前就被设计出来了,如果今天重新设计,我们可能不会重复一些已经做出的选择。 - M.M
4
“这更像是一道哲学问题而不是技术问题” - 这个问题不太适合在StackOverflow上提问。如果你想知道为什么设计是这样的,请向标准委员会提问。 - Remy Lebeau
谢谢@Remy,我可能会这样做。 - bliutwo
1
@M.M -- std::string(更准确地说,std::basic_string)是在最初的C++标准化工作中设计的,作为C++98的一部分。在标准化工作开始之前,它并不存在。 - Pete Becker
@PeteBecker 你可能比任何人都更适合回答这个问题。 - M.M
@M.M -- "better placed" 不意味着 "well placed" <g>。是的,Uwe Steinmueller 和我设计了最初的 std::string(也许是在有 std:: 之前),但我不记得那个层面上的细节,我怀疑其他人也不记得。我可以想出差异的原因(对 "不同不等于相同" 的扩展),但我不能说那些是实际的原因。请参见 Davis Herring 的答案。 - Pete Becker
1个回答

1
在每种情况下,都有带有和不带有进一步整数参数的重载;我们可以将它们视为可选项。对于从const char*构造函数来说,一个额外的参数是大小(如果输入没有以空字符结尾,则需要); 如果您想要一个起始偏移量,只需编写std::string(p + off, sz),因此没有必要将其作为参数提供。
然而,在复制另一个string对象时,std::string(s.data()+off,sz)是迂回且不安全的。没有源对象,无法防止使用偏移或显式大小超出源对象;从历史上看,data()并不总是(保证)以空字符结尾,使得这样的用法在没有大小的情况下是不安全的。因此,针对类似于复制的构造函数提供了起始偏移量和大小 - 按照顺序提供,因为那更加自然 - 如果您只提供一个,则必须是偏移量。

当一个字符串包含嵌入的空字符时,需要使用接受const char*和长度的构造函数。 - Pete Becker
@PeteBecker:当然可以,尽管这可能被认为是非空终止的另一个例子(也许它在结尾确实有一个空字符,但你怎么知道它是结尾呢?)。 - Davis Herring
重点是普通的C字符串以空字符结尾;在空字符之后,您无法对任何内容进行操作。std::string(const char*,size_type)不将指针视为指向C字符串中第一个元素的指针,而是将其视为指向没有特殊含义的char数组的指针。 - Pete Becker

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