【问题标题】:C++ std::string::insert(string::iterator, char) iterator not randomC++ std::string::insert(string::iterator, char) 迭代器不是随机的
【发布时间】:2014-09-14 02:00:23
【问题描述】:

我正在尝试在字符串中插入一个字符:

#include <Rcpp.h>
#include<string>
using namespace Rcpp;

f(std::string a){
std::string::iterator i=a.begin()+1;
a.insert(i,',');
std::cout<<a<<"\n";
std::cout<<*i<<"\n";
std::cout<<*(i-1)<<"\n";
}

f("abcd") 将打印:

"a,bcd"
"b"
"a"

我认为 *(i-1) 是 ","。似乎迭代器在这里坏了?所以我不应该将 std::string::iterator 与 std::string 一起使用,就像将 std::vector::iterator 与 std::vector 一起使用?

谢谢!

【问题讨论】:

  • 这是未定义的行为。调用 insert 后,std::string 的迭代器可能会失效。
  • 关于这一点的官方文本:引用 basic_string 序列元素的引用、指针和迭代器可能会因该 basic_string 对象的以下用途而失效: — 作为任何标准的参数将非常量 basic_string 的引用作为参数的库函数。 — 调用非常量成员函数,除了 operator[]、at、front、back、begin、rbegin、end 和 rend。
  • 关于最后一句,std::vector的迭代器也有同样的问题。
  • 这令人心碎!@chris
  • 你太棒了! @MattMcNabb

标签: c++


【解决方案1】:

这是因为string::iterator 是一个双向迭代器,这意味着i 指向下一个和上一个迭代器(我们称其为成员nextprev

插入后i 未被修改,因此它的prev 成员仍指向它之前指向的相同迭代器(即a.begin(),顺便说一句)。

【讨论】:

  • 它是一个随机访问迭代器(仍然满足双向迭代器的要求)。不过,这不是重点。如果您有一个指向数组中某个元素的指针,并且您为该数组重新分配了更多空间并将其移动,您希望该指针有什么用处?它可能会发生,但无论哪种方式都是未定义的行为。
  • 我没有说这个点是好是坏,我说的是它指向的地方,以便用户可以理解发生了什么。迭代器可能会失效,但在这种情况下它不是。不要误会,字符串上下文中的迭代器是无效的,但是指针仍然是指向有效内存地址的指针。
【解决方案2】:

插入操作可能会使迭代器无效(因为它可能会导致内存重新分配,并且迭代器不会神奇地移动到新位置)。

要解决此问题,请执行i = a.insert(i, ',');

另外,这与 Rcpp 无关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多