std::string::iterator是否保证不是char指针?

5
考虑到在§21.4中,标准规定了std::string类的概述如下,并且考虑到存在一个针对指向char的指针的std::ostream上的operator<<的重载,请注意。
namespace std {
  template<class charT, class traits = char_traits<charT>,
    class Allocator = allocator<charT> >
  class basic_string {
  public:
    [...]
    typedef implementation-defined iterator;
    typedef implementation-defined const_iterator; 
    [...]
  };
}

最后,鉴于对于Container概念中iteratorconst_iterator的要求,在§23.2/4中:

enter image description here

而一个指向 char 的指针将满足他们的需求;我是否正确理解,以下代码是否编译取决于其实现方式?

std::string string = "abc";
std::cout << begin(string);

顺便提一下,GCCClang似乎都不接受它。


2
不是_实现定义_:实现不需要记录迭代器的类型。然而,实现可以使用类或指针类型。 - Dietmar Kühl
2
@DietmarKühl 如果迭代器的类型不是实现定义的,那么为什么在basic_string的概要中它们被标记为“实现定义”? - Shoe
根据你在帖子中已经描述的内容,我会对你在帖子中的问题回答“是”,而对标题中的问题回答“否”。 - R Sahu
3
在C++11之前,据我所知,底层存储不需要以空字符结尾。因此,即使迭代器类型为“char*”,你也不能假设它是以空字符结尾的字符串(在C++11之前)。 - melak47
@melak47 这实际上是一个非常好的观点。 - Shoe
显示剩余2条评论
2个回答

2

简短回答:不行。

长话短说:

这可能取决于您在“指向char的指针”措辞中放置的内容。它可以严格解释为正式类型char*或类似类型,也可以更松散地解释为任何指向存储字符的内存地址。

我没有看到您提到的重载实际上存在于标准中,但仍然有可能存在其他必需的重载。您所举的例子似乎不存在(似乎没有其他地方使用std::string :: iterator char * 进行重载),例如,您无法输出 std :: string :: iterator

std::string s = "abc";
std::string.iterator p = s.begin();

std::cout << p; // fails

由于标准规定方法和函数应该存在,即使我们认为实现不需要像标准中指示的那样正式定义它们,只需要表现得好像已经定义了(比较翻译序列的要求),你仍然可能需要区分重载,因为你应该能够取一个指向它们的指针(你需要知道该指针应该具有什么类型)。
例如,如果我们有一个规范,说它应该表现得好像定义了void foo(long)void foo(int),而实现实际上只包含void foo(long),只要程序只发出对foo的函数调用,就可以正常工作,因为shorts会被静默地转换为int,但是一旦某个程序包含代码来获取函数的指针,它就会失败,因为它存储指针的类型根本不匹配。
 void foo(long);

 foo(1L); // works fine
 foo(1);  // works probably fine, 1 is converted to long first

 void (*f)(int) = foo;  // this fails as it cant convert void(*)(long) to void(*)int

我们可以得出结论,std::string::iterator 可能需要不同的正式类型(即使存在 char*std::string::iterator 之间的重载)。请注意,即使出现 char*char const* 仍然是一个不同的类型。
然而,如果你只是指“指向字符的指针”仅表示字符的内存地址(不一定是 char* 类型),那么它确实可以。甚至可以说,这可能是相当可能的。

抱歉,你的回答的一半(第一段、最后一段和第三段的后半部分)是关于我是否说“指向char”的,而不是“指向const char”的? - Shoe
@Jeffrey 不是,这是“指向字符的指针”和char*之间可能存在的区别,前者可以更自由地解释,正如我在最后一节中讨论的那样。 - skyking
为什么函数重载是 char*,指向 char 的指针或 CharT const* (假设类型名为 CharT) 很重要呢?对我来说似乎并不重要,如果这对你很重要,请随意编辑我的问题并澄清哪个重载会被选中以传递 char* - Shoe
第二段对我来说完全是个谜。我不知道你想说什么。你能重新表述一下吗?第一行中的“these”是什么意思?当你需要能够获取它们的指针时,你仍然可能需要区分重载函数,因为这是你应该能够做到的。 - Shoe
这个区别对我来说并不重要,我的回答涵盖了两种可能性。如果你认为我不应该同时涵盖两种情况很重要,那么我认为你应该编辑你的问题。 - skyking
@Jefffrey 不用担心这个谜团,它只是说库的实现需要与标准中声明的函数签名相同,无论如何解释。然而,这个有问题的方法似乎根本不存在。 - skyking

0

std::string的迭代器的实际类型是由实现定义的。没有要求它们必须是指针,也没有要求它们不是指针。

标准流也没有要求具有接受任何标准容器(包括std::string)的迭代器的operator<<()变体。反之亦然,也没有要求它不应该有。这意味着在您的帖子末尾的代码是否编译是由实现定义的。


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