一个简单的例子,我在说什么:
#include <algorithm>#include <iostream>#include <string>#include <vector>class RecentStringBuffer{public: const std::string & at(size_t index) { return v.at(index); } voID add(const std::string & s) { // Remove any prevIoUs occurances v.erase(std::remove(v.begin(),v.end(),s),v.end()); // Prepend the new entry v.insert(v.begin(),s); // Truncate older entrIEs v.resize(std::min<size_t>(v.size(),maxEntrIEs)); }private: const int maxEntrIEs = 10; std::vector<std::string> v;};int main(){ RecentStringBuffer r; r.add("A"); // r == [A] r.add("B"); // r == [B,A] r.add("C"); // r == [C,B,A] r.add(r.at(1)); // r == [B,C,A] one would assume? std::cout << r.at(0) << r.at(1) << r.at(2); // Prints "A C A"}
在这个例子中,我们得到了一个令人惊讶的结果,但是如果v已经重新分配了,那么这个引用将被留在v的内存之外,这会更糟.在技术上,参考无论如何都是无效的,所以发生的是未定义的行为.
类似的情况显然会发生在全局变量而不是数据成员和指针而不是引用,但成员和引用通常会更安全,所以这似乎是一个更令人惊讶的陷阱.
现在,我不是问为什么会发生这种情况(我了解发生了什么)或如何解决(有几个明显的方法).我的问题与最佳做法有关:
>这个问题有没有名字?
谁负责担心这个问题?
>或者说另一种方式,错误在哪里在上面的应用程序?当单独查看时,似乎完全合理和有益于at()返回一个const引用和add()来接受一个.另一方面,如果调用者main()也应该更好地知道似乎并不公平,特别是考虑到引用可能会在问题发生之前通过多个函数传递.
>有没有一般的策略来注意和避免这样的结构?
如果一个功能不支持这一点,那么它应该是清楚的.
标准库的一个例子是:
> std :: vector :: insert(const_iterator pos,inputIt first,inputIt last)被具体记录为说“如果第一个和最后一个是迭代器到* this的行为是未定义的”.
> std :: vector :: insert(const_iterator pos,const T& value)没有这样的文档,因此即使值指向向量的元素,它也必须工作. (这是确认by the committee).
所以,在你的代码中,你需要修改add()来工作,即使s是指v的成员;或记录它不会工作.
总结以上是内存溢出为你收集整理的c – 如何处理可能指向内部数据的参考论据?全部内容,希望文章能够帮你解决c – 如何处理可能指向内部数据的参考论据?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)