Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 拆卸及维修;使用迭代器时在STL中添加元素_C++_Vector_Insert_Iterator_Invalidation - Fatal编程技术网

C++ 拆卸及维修;使用迭代器时在STL中添加元素

C++ 拆卸及维修;使用迭代器时在STL中添加元素,c++,vector,insert,iterator,invalidation,C++,Vector,Insert,Iterator,Invalidation,我被我正在读的那本书的摘录弄糊涂了 我不明白为什么这本书证明对STL使用删除和添加操作是合理的,尽管这会导致迭代器无效。有人能告诉我这本书想要传达的信息吗?在本例中,insert和erase的返回值被分配给iter。这两种方法都会使容器中现有的迭代器无效,但它们返回的迭代器是有效的。作者试图指出的一点是,虽然vector::insert和vector::erase可能会使以前创建的迭代器无效,但它们返回的迭代器必然有效,因此您可以依赖它们 检查此表以准确了解每个STL容器何时发生iter/r

我被我正在读的那本书的摘录弄糊涂了


我不明白为什么这本书证明对STL使用删除和添加操作是合理的,尽管这会导致迭代器无效。有人能告诉我这本书想要传达的信息吗?

在本例中,
insert
erase
的返回值被分配给
iter
。这两种方法都会使容器中现有的迭代器无效,但它们返回的迭代器是有效的。

作者试图指出的一点是,虽然
vector::insert
vector::erase
可能会使以前创建的迭代器无效,但它们返回的迭代器必然有效,因此您可以依赖它们


检查此表以准确了解每个STL容器何时发生iter/ref失效:

即使这些操作使(某些)旧的、预先存在的迭代器失效,也不会阻止新创建的迭代器有效。示例程序将无效迭代器的值指定为有效值(文本使用的单词中的“resets”)

这是一个不同但类似的例子:

int* ptr;     // an iterator

{
    int i;
    ptr = &i; // ptr is now valid
} // ptr has become invalid because storage duration of i ended

int j;
ptr = &j; // ptr is valid again despite having been invalid earlier

<> >起首起于C++ 14标准,在成员函数<代码>擦除< /代码>和<代码> INSERT 现在,相应的成员函数(在代码段中使用)声明如下

iterator insert(const_iterator position, const T& x);
iterator erase(const_iterator position);
所以你可以写

auto iter = vi.cbegin();
而不是

auto iter = vi.begin();
并在调用
erase
insert
时使用它

使用成员函数
insert
将新元素添加到向量后,向量可以在内部重新分配其元素的内存。在这种情况下,当前迭代器可能无效,因为它将在重新分配之前指向内存

但是该函数返回一个迭代器,该迭代器指向存储在已重新分配的内存中的新插入元素。因此,返回的迭代器将指向内存的实际范围

考虑以下演示程序

#include <iostream>
#include <vector>
#include <iterator>

int main() 
{
    std::vector<int> v;
    
    v.insert( v.cbegin(), 0 );
    
    std::cout << "v.data() = " << v.data() 
              << ", &v[0] = " << &v[0] << '\n';
    
    v.insert( v.cbegin(), 1 );
    
    std::cout << "v.data() = " << v.data() 
              << ", &v[0] = " << &v[0]
              << ", &v[1] = " << &v[1] << '\n';
    
    
    return 0;
} 
如你所见,在插入第二个值之后,向量在内存内部重新分配了元素的存储位置。即在插入第二个值之前,函数
cbegin
返回的当前迭代器指向地址为
0x556699d79e70
的内存范围。插入第二个值后,函数
cbegin
返回的当前迭代器将指向地址为
0x556699d7aea0
的内存范围。也就是说,前一个当前迭代器无效

但是如果你用下面的方法重写程序

#include <iostream>
#include <vector>
#include <iterator>

int main() 
{
    std::vector<int> v;
    auto iter = v.cbegin();
    
    iter = v.insert( iter, 0 );
    
    std::cout << "v.data() = " << v.data()  
              << ", &*iter = " << &*iter << '\n';
    
    iter = v.insert( iter, 1 );
    
    std::cout << "v.data() = " << v.data() 
              << ", &*iter = " << &*iter << '\n';
    
    
    return 0;
}
迭代器
iter
始终指向有效的内存范围,因为它是由函数insert返回的迭代器重新分配的,结果指向有效的内存范围


这同样适用于成员函数
erase
。函数迭代器返回的结果无效。

From:“不要发布代码、数据、错误消息等的图像-复制或在问题中键入文本”-我看不懂您的图片,但如果要猜,他们使用的事实是
erase
将有效迭代器返回到被删除元素之后的元素。这是关于
std::set
的,但问题类似。供参考:
#include <iostream>
#include <vector>
#include <iterator>

int main() 
{
    std::vector<int> v;
    auto iter = v.cbegin();
    
    iter = v.insert( iter, 0 );
    
    std::cout << "v.data() = " << v.data()  
              << ", &*iter = " << &*iter << '\n';
    
    iter = v.insert( iter, 1 );
    
    std::cout << "v.data() = " << v.data() 
              << ", &*iter = " << &*iter << '\n';
    
    
    return 0;
}
v.data() = 0x55d8c5698e70, &*iter = 0x55d8c5698e70
v.data() = 0x55d8c5699ea0, &*iter = 0x55d8c5699ea0