Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.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++ C++;容器在使用前销毁/修改时发出警告(通过引用元素或迭代器使用)_C++_Containers - Fatal编程技术网

C++ C++;容器在使用前销毁/修改时发出警告(通过引用元素或迭代器使用)

C++ C++;容器在使用前销毁/修改时发出警告(通过引用元素或迭代器使用),c++,containers,C++,Containers,我将从我最近遇到的一个问题开始——我有一个向量,我获取了它的迭代器,我存储了迭代器(begin,end),然后容器超出了范围,因此被销毁。我不记得有任何编译器警告。这是一个很难的调试,因为我只有在非常大的数据集上运行时才得到segfault。在容器修改(放大/缩小)/销毁后,使用迭代器/对容器项的任何引用时,是否存在编译器错误/警告的方法?我错过什么了吗?我认为它与const限定符同样重要,因为没有人希望引用一个混乱容器中的项目,对吗 我被迫回忆起上面的情况,因为现在我有另一个作业——创建一个特

我将从我最近遇到的一个问题开始——我有一个向量,我获取了它的迭代器,我存储了迭代器(begin,end),然后容器超出了范围,因此被销毁。我不记得有任何编译器警告。这是一个很难的调试,因为我只有在非常大的数据集上运行时才得到segfault。在容器修改(放大/缩小)/销毁后,使用迭代器/对容器项的任何引用时,是否存在编译器错误/警告的方法?我错过什么了吗?我认为它与
const
限定符同样重要,因为没有人希望引用一个混乱容器中的项目,对吗

我被迫回忆起上面的情况,因为现在我有另一个作业——创建一个特定的容器。我必须返回一个代理引用,而不是对某个项(即某个内存位置)的引用,因为在分配给代理引用后,容器的一部分必须写入磁盘。但仅仅是为了获取信息,这也许并不重要,在这个问题上,它同样可以是一个正常的参考。我希望将此返回代理引用的方法(或任何返回迭代器的方法)标记为“锁定”,这意味着在引用/迭代器的生命周期内,容器将有效地作为
常量运行。(虽然不同的
常量
,允许修改单个项目,但禁止修改容器(比如宏属性),例如,允许运算符[]在此“宏常量”对象上返回非常量引用)

如何在C++中实现这一点?这个概念是否存在于其他语言中?或者为什么它不起作用? 正如我前面所说的,我假设这个概念足够普遍,因为第一个数据结构是任何程序的构建块,第二个原因是没有人希望引用混乱容器中的项


在容器修改(放大/缩小)/销毁后,使用迭代器/对容器项的任何引用时,是否存在编译器错误/警告的方法

对。这叫做静态分析器。如果您使用的是llvm,则可以帮助您在释放内存后找到内存的一些用途。其他编译器也有类似的工具。它们还可以告诉您其他有用的事情,例如何时可以在不初始化的情况下使用变量,以及类似的事情

我想将这个返回代理引用的方法(或任何返回迭代器的方法)标记为“锁定”,这意味着在引用/迭代器的生命周期内,容器将有效地作为常量运行。(虽然是不同的常量,允许修改单个项目,但禁止修改容器,比如说宏属性


我不知道有什么方法可以使编译器在修改容器时向您发出错误或警告。但是可以使用或锁定对资源的访问。这将阻止其他代码在您使用容器时修改容器。您还可以编写容器修改方法,以便它们
抛出概括一下您的问题,通常最好传递/保留指向实际容器的引用或指针,而不是迭代器,因为迭代器应该被视为是短期的——它们在许多操作(例如插入和删除元素)中无效

要处理生存期,您可以向对象传递(或返回)一个
std::shared_ptr
,以确保该对象在仍由程序的另一部分使用时不会解除分配

关于调试,除了@user1118321提到的静态分析之外,您还可以使用地址消毒器(对于clang,请编译并链接
-fsanize=address
,在您的情况下,这将导致程序终止,并出现错误
AddressSanitizer:heap use after free
,以及一份关于发生情况的非常详细的报告


关于您关于“锁定”的问题,受@melpomene关于使用Rust的评论启发:通过将对象移动(使用
std::move()
)到另一个函数(从而“锁定”它),您可以获得类似于借用Rust的语义然后返回它,但是在调用函数返回(“返回/解锁”)对象之前,你不能使用这个对象。

HAH。这听起来好像你想用锈而不是C++。“有没有办法编译错误/警告”--编译器只知道它正在编译的单个源文件。如果您正在编译一个函数,该函数接收指向向量的指针,则该函数调用另一个源文件中定义的第二个函数,返回后使用向量的内容,编译器无法知道第二个函数是否
delET/<代码> D向量,或者第一个函数不能使用向量。编译器没有办法警告你。欢迎来到C++。@ SavaVaveKik好了,编译器不是,但是链接器。如果人们能看到它(如果他们每次注意都不注意),计算机也可以。除非有一个陷阱,它不能总是确定,而且经常发生。不,链接器不会反编译每个模块并尝试对其进行反向工程。不会发生。