std::strings1{"现代C++",3}与std::strings1{str,3}
以下代码的输出让我感到困惑:
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";
输出:
> S1: Mod
> S2: ern C++
谁能解释这个结果?
回答
从:
https://en.cppreference.com/w/cpp/string/basic_string/basic_string
std::string s1 {"Modern C++", 3};
使用以下构造函数:
basic_string( const CharT* s,
size_type count,
const Allocator& alloc = Allocator() );
所以需要 3 个字符才能得到Mod.
std::string s2 {str, 3};
将使用以下构造函数:
basic_string( const basic_string& other,
size_type pos,
const Allocator& alloc = Allocator() );
所以从位置 3 开始取字符串给 : ern C++。
- One has to ask why they'd ever add two constructors with such differing behavior. Its like it was cobbled together with no thought at all.
- @Polygnome: "Cobbled together with no thought at all" basically describes the whole of `std::string`. It also accounts for the mix of index-based and iterator-based methods -- string was developed independently of the STL, then retroactively augmented to match -- and in general has too many "convenience methods. I always like [GOTW #84: Monoliths Unstrung](http://www.gotw.ca/gotw/084.htm) which dives into a minimal string API supplemented by free functions.
- Thank you. the first one is `size_type count` and the second is `size_type pos`.
- Is there even a use case for this substring constructor that wouldn't be served by the `substr` method?
回答
一个是打电话string(char const*, count),另一个string(string const&, pos)。
一个从缓冲区中获取前 3 个字符,另一个获取第 3 个字符之后的所有字符。
这是因为 C++ 具有原始字符缓冲区和标准字符串。 "this is not a std::string". "this is a std string"s, std::string so_is="this";.
std::string 已有30多年的历史,并且在没有足够小心的情况下被添加到C++语言中(与STL不同,它在添加之前经历了更多的迭代)。
老实说,它的界面太丰富了,你可能会遇到这样的东西;导致混乱结果的多个重载。
回答
谁能向我解释这是为什么?
那是因为std::string有它不应该的构造函数(@ORR解释了细节)。它不应该有这些构造函数,因为:
- 使用命名构造函数习语/
std::string方法和现有构造函数可以轻松实现它们的效果- 无需额外成本(至少在 C++11 中),并且 - 仅通过查看构造函数调用来理解构造函数参数的使用方式并不明显和微不足道。
这不是标准库中具有这种不良(恕我直言)构造函数的唯一情况;std::vector因构造函数种类繁多和令人困惑/误导性的构造函数语义而(臭名昭著)。
人生课程:
- 省略构造函数;并非所有用于构造类对象的常用值都应该有自己的构造函数;
- 相反,使用命名构造函数惯用语。
- 让你的代码审查者或其他一些不那么偏见的人阅读你的构造函数的调用,以判断每个构造函数的含义是否足够明显。
THE END
二维码