C++ std::string s1{“现代C+;”和#x2B;”,3}vs std::string s1{str,3}

C++ std::string s1{“现代C+;”和#x2B;”,3}vs std::string s1{str,3},c++,string,c++17,C++,String,C++17,以下代码的输出使我感到困惑: const std::string str = "Modern C++"; std::string s1 {"Modern C++", 3}; std::string s2 {str, 3}; std::cout << "S1: " << s1 << "\n"; std::cout << "S2: " <<

以下代码的输出使我感到困惑:

const std::string str = "Modern C++";

std::string s1 {"Modern C++", 3};
std::string s2 {str, 3};

std::cout << "S1: " << s1 << "\n";
std::cout << "S2: " << s2 << "\n";
有人能解释这个结果吗?

来自:

使用以下构造函数:

basic_string( const CharT* s,
          size_type count,
          const Allocator& alloc = Allocator() );
basic_string( const basic_string& other,
          size_type pos,
          const Allocator& alloc = Allocator() );
因此需要3个字符才能获得
Mod

std::string s2 {str, 3};
将使用以下构造函数:

basic_string( const CharT* s,
          size_type count,
          const Allocator& alloc = Allocator() );
basic_string( const basic_string& other,
          size_type pos,
          const Allocator& alloc = Allocator() );

因此,从位置3开始取字符串,给出:
ern C++
一个调用
字符串(char const*,count)
,另一个调用
字符串(string const&,pos)

一个从缓冲区中获取前3个字符,另一个从第3个字符后获取所有字符

这是因为C++有原始字符缓冲区和STD字符串。代码>“这不是std::字符串”<代码>“这是一个标准字符串”,

std::string so_is=“this”

<代码> STD::String 已经超过30年了,它被添加到C++语言中,没有足够的关心(不像STL,在添加之前经过了更多的迭代)。 它的界面实在太丰富了,你可以碰到这样的东西;导致混乱结果的多个重载

谁能解释一下为什么会这样

这是因为
std::string
具有它实际上不应该使用的构造函数(@ORR详细信息)。它不应该有这些构造函数,因为:

  • 使用/
    std::string
    方法和现有构造函数可以很容易地实现它们的效果,而不需要额外的成本(至少在C++11中),并且
  • 仅仅从构造函数调用的角度来理解构造函数参数是如何使用的,这并不明显,也不重要
  • 在标准库中,这不是唯一一个具有这种可拒绝(IMHO)构造函数的情况;以混淆/误导构造函数语义而闻名

    生活课程:

    • 吝啬建筑工人;并不是每一个用于构造类对象的常用值都应该有自己的构造函数
    • 相反,使用
    • 让您的代码审阅者或其他不太偏袒的一方阅读对构造函数的调用,以判断每一个构造函数的含义是否足够明显

    如果您希望获得与

    s1的Mod

    s2的Mod

    您可以为str使用char指针,例如

    char * str = "Modern C++";
    
    std::string s1 {"Modern C++", 3};
    std::string s2 {str, 3};
    
    std::cout << "S1: " << s1 << "\n";
    std::cout << "S2: " << s2 << "\n";
    

    你读过
    std::string
    构造函数吗<代码>“现代C++”
    不是一个
    std::string
    ,而是一个字符数组(它会自动转换为字符指针),并且有一个不同的构造函数。当然。推荐人会告诉你的。我确信这些聪明的原因是因为这些不做同样的事情,C++图书馆委员会将用完美的逻辑和推理来证明我。然而,这仅仅是一个原因——虽然小,C++标准库仍然是不直观的,甚至令人沮丧,使用。@霍利布莱克特,但是结果应该是一样的,无论如何谢谢。“惊人聪明的原因”是STD::字符串最初是几十年前设计的。因此事后看来,它的一些构造函数和功能与我们认为的现代直觉是不相称的。interface@M.M.:这一点,再加上C风格的字符串是在很久以前设计的,而且
    std::string
    必须与它们的约定一起工作。也就是说,这两种语言可能都应该使用相同的C风格字符串语义,而不是将位置作为
    std::string
    的有效起点和
    char*
    的有效终点,因此您的观点仍然有效,只是要指出,这个领域的兼容性约束甚至早于
    std::string
    。谢谢。第一个是
    size\u-type-count
    ,第二个是
    size\u-type-pos
    。人们不得不问,为什么他们会添加两个行为如此不同的构造函数。这就像是在没有任何思想的情况下拼凑在一起。@Polygenme:“拼凑在一起根本没有思想”基本上描述了整个
    std::string
    。它还解释了基于索引和基于迭代器的方法的混合——字符串是独立于STL开发的,然后追溯性地扩展以匹配——通常有太多“便利方法。我总是喜欢将其深入到一个由自由函数补充的最小字符串API中。这个子字符串构造函数是否有一个不会由
    substr
    方法提供的用例?为了让它工作,第一行应该是:char str[]=“Modern C++”;或char str[]{“现代C++”};试试看,对我来说效果很好。在c++/c中,还可以用指针声明和初始化字符数组。char*str=“现代C++”;使用str[value]循环,因为str现在是一个数组。我相信没有[]的语法是char**str.
    char*str=“Modern C++” Mod
    
     Mod