在范围 (C++) 之外列出插入迭代器
List insert iterator outside range (C++)
>我有一个可以响应doSomething()
的类A
和一些子类B
、C
和D
,它们都覆盖了doSomething()
。 B
特别有一个实例变量,它是标准库中的列表,并在响应doSomething()
时将元素添加到此类列表中。
在我的代码的某些部分,我创建了一个数组,其中包含指向 A
类型的对象的指针。现在,如果我这样声明:
A* pointersToA[3];
pointersToA[0] = &B();
pointersToA[1] = &C();
pointersToA[2] = &D();
打电话给pointersToA[0]->doSomething()
时我得到了一个List insert iterator outside range
.
但是如果我这样做:
A* pointersToA[3];
B b = B();
pointersToA[0] = &b;
pointersToA[1] = &C();
pointersToA[2] = &D();
一切都按预期工作。
为什么会这样?
获取右值的地址几乎可以保证迟早(通常更早)会导致问题,并且实际上在C++中是非法的(因此您的编译器在这方面并不完全是一流的)。地址不是对对象的强引用;由于C++不是垃圾回收语言,因此一旦执行了B
、C
和D
的值,它们就会消失。
对于您的使用,动态分配听起来是最直接的方式:
std::array<std::unique_ptr<A>, 3> pointersToA {
std::make_unique<B>(),
std::make_unique<C>(),
std::make_unique<D>()
};
当你这样做时:
pointersToA[0] = &B();
您正在pointersToA[0]
中存储指向临时的指针。这在标准C++中无效,符合要求的实现应发出错误。这个编译器的事实表明你的编译器有一个错误或非标准扩展。
假设编译器接受该代码,则问题在于,在该行之后,pointersToA[0]
将失效,因为它指向的B
对象不再存在。取消引用该指针是未定义的行为。
当你这样做时
B b = B();
pointersToA[0] = &b;
存储指向对象 B 的指针。只要 b 还活着,就可以通过 pointersToA[0]
访问它。
注意:最好在编译器中禁用此"扩展"以避免遇到此类问题。
pointersToA[0] = &B();
这将创建一个临时对象,调用其构造函数,将指向该对象的指针存储在 pointersToA[0] 中,然后临时对象被销毁,调用其析构函数。从这一点开始,指针ToA[]中存储的指针不再有效,并且使用它是一种未定义的行为。
B b = B();
pointersToA[0] = &b;
在这里,对象继续存在,直到此作用域结束,使用此指针、取消引用它、调用其方法是一个有效的操作,直到作用域结束,并且对象被销毁。
您收到的错误消息是由于未定义的行为。"未定义的行为"意味着任何东西:代码仍然运行,产生正确的结果;或者代码仍在运行,产生垃圾结果;或者代码失败并出现一些随机错误;或者您的整个计算机着火并爆炸。
创建指针并存储它,则需要智能指针类或新建。您实际上正在做的是创建一个临时对象,然后将指针存储到它以前所在的位置,因此当您调用 b::d oSomething() 时,您正在调用一个已经销毁的对象。
#include <iostream>
class base {};
class derived : public base {
public:
derived() { std::cout << "constructed" << std::endl;}
~derived() { std::cout << "destructed" << std::endl;}
};
int main(){
base *pointers[3];
pointers[0] = &derived();
std::cout << "pointer assigned" << std::endl;
return 0;
};
输出:
constructed
destructed
pointer assigned
- 列表的有效性在插入后开始迭代器
- C++ 向量插入和迭代器混淆
- 在插入容器之前转换输出迭代器
- 插入 boost::multi_index 后迭代器变得无效?
- unordered_set范围插入与迭代器
- 如果迭代器没有因插入而无效,则使用std::find和C::insert()是线程安全的
- 使用条件迭代器插入到向量中
- 向量<pointer>:插入(迭代器,指针)插入垃圾值
- 并行STL插入迭代器,例如std :: back_insert_iterator
- unordered_map在结束迭代器上插入
- 重新插入元素可以"re-validate"迭代器吗?
- 插入新元素时结束迭代器会获得更新
- 使用迭代器将值插入嵌套地图
- 如何使用迭代器插入std ::列表
- 在 std::vector 中插入迭代器范围
- 如何普遍有效地填充缓冲液?(传递插入迭代器?器皿?等)
- 在范围 (C++) 之外列出插入迭代器
- 插入迭代器与容器的成员函数插入器
- C++列表在范围外插入迭代器
- 映射插入迭代器绑定