为啥 C++ 共享指针的行为不像迭代器的标准指针?

Posted

技术标签:

【中文标题】为啥 C++ 共享指针的行为不像迭代器的标准指针?【英文标题】:Why does C++ shared pointer not behave like standard pointer for iterators?为什么 C++ 共享指针的行为不像迭代器的标准指针? 【发布时间】:2013-05-29 19:24:03 【问题描述】:

我即将在 C++ 中创建一个随机数生成器,为了避免复制太大的向量,我想将指针传递给它们。我不想自己处理垃圾收集。这就是我想使用 shared_ptr 的原因(我可能会补充说我是新手,所以也许我的方法很笨拙/不适合这个问题。)。现在我想搜索向量,但是 shared_ptr 和 shared_ptr.get() 分别有一个奇怪的行为:要么他们没有找到正确的解决方案(参见代码 sn-p),要么他们甚至抛出了一个

MonteCarlo.exe 中 0x0131F5DA 处的第一次机会异常:0xC0000005:访问冲突读取位置 0x00000008。

在其他情况下。我看到位置接近 0(= 空指针),但为什么呢?

使用标准指针会产生正确的结果。 这是我的代码sn-p:

    #include <typeinfo>
#include <algorithm> 
#include <vector>
#include <memory>
using namespace std;

int j = 3;    
vector< int > v;  
v.push_back(1);  
v.push_back(3);  
v.push_back(5);
vector< int >* v_pointer = &v;
shared_ptr<vector< int >> v_shared = make_shared<vector<int>>();
vector< int >* v_pointer_from_shared = v_shared.get();

// printing types of objects
cout << typeid(v.begin()).name() << endl;
cout <<  typeid(v_pointer->begin()).name() << endl; 
cout << typeid(v_shared->begin()).name() << endl;

// do search
if (binary_search(v.begin(), v.end(), j)) cout << "yeah" << endl;
if (binary_search(v_pointer->begin(), v_pointer->end(), j)) cout << "yeah2" << endl;
if (binary_search(v_shared->begin(), v_shared->end(), j)) cout << "yeah3" << endl;
if (binary_search(v_pointer_from_shared->begin(), v_pointer_from_shared->end(), j)) cout << "yeah4" << endl;

输出:

是的

是的2

那么为什么yeah3 没有出现呢?因为 typeid 是相同的……或者至少是 yeah4,这又是一个普通的指针。我想,有一些关于 shared_pointers 的理论我不明白......

我在 64 位 Windows 7 上使用 VS 2012 Express。

【问题讨论】:

好吧,AFAICS,你的共享指针永远不会被设置为指向v。 (另请注意,您应该使用共享指针指向非动态分配的内存。) ...所以你绝对不应该那样使用共享指针。共享指针需要对它们指向的内容进行独占清理控制:在这种情况下,如果 v 超出范围但 shared_ptr 引用之一在附近,它将使 shared_ptr 引用无效,这有点违背了使用 shared_ptr 的目的, 并且当他们试图清理一个已经清理的 v 时,当它们超出范围时会使它们爆炸。你应该有 'shared_ptr> v_pointer(new vector())'。 @OliCharlesworth 当然你的意思是你应该使用共享指针来指向动态分配的内存? 非常感谢您的快速回复!我真的需要阅读一些关于何时/如何使用哪种指针的信息。 【参考方案1】:

看看你是怎么设置shared_ptr和普通vector的:

int j = 3;    
vector< int > v;  
v.push_back(1);  
v.push_back(3);  
v.push_back(5);
vector< int >* v_pointer = &v;
shared_ptr<vector< int >> v_shared = make_shared<vector<int>>();
vector< int >* v_pointer_from_shared = v_shared.get();

您从未在shared_ptr 指向的vector 中插入任何内容,因此执行binary_search 时的正确行为是报告vector 中不存在任何值。请注意,v 和您指向的 vector 不是相同的 vector,也不应该是相同的。

希望这会有所帮助!

【讨论】:

非常感谢!愚蠢的我,自从我上次使用指针以来已经有一段时间了。我可以问一下你的意思是什么注意v和你指向的向量不是同一个向量,也不应该是。我认为v。v_pointer-> 是完全一样的吗?但也许我误解了你想表达的意思。

以上是关于为啥 C++ 共享指针的行为不像迭代器的标准指针?的主要内容,如果未能解决你的问题,请参考以下文章

C++中的迭代器

迭代器的解释

c++中迭代器的问题为啥这样会报错?

C++ 的STL中,迭代器那个指针为何++能指向下一个元素?

STL略观——deque迭代器的一些关键行为

stl中vector中erase后迭代器为啥会失效