gpt4 book ai didi

c++ - boost::python 和 set::erase -> 奇怪的行为

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:17:12 26 4
gpt4 key购买 nike

我正在尝试将对象存储在 std::set 中。这些对象是 boost::shared_ptr<>,来自 python 环境。向集合中添加值不会造成任何麻烦。但是当我试图删除一个值时,即使我传递的是完全相同的引用,它也不会起作用。这是一个例子:

#include <set>
#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/python.hpp>

using namespace std;
using namespace boost;
using namespace boost::python;

struct Bar
{
Bar() {}
};

struct Foo
{
set< shared_ptr<Bar> > v_set;
shared_ptr<Bar> v_ptr;

Foo() {}

void add( shared_ptr<Bar> v_param ) {
cout << "storing " << v_param << "in v_set and v_ptr" << endl;
v_set.insert(v_param);
v_ptr = v_param;

}

void del( shared_ptr<Bar> v_param ) {
cout << "deleting " << v_param << endl;
if (v_param == v_ptr) {
cout << "v_param == v_ptr" << endl;
} else {
cout << "v_param != v_ptr" << endl;
}

cout << "erasing from v_set using v_param" << endl;
if (v_set.erase(v_param) == 0) {
cout << "didn't erase anything" << endl;
} else {
cout << "erased !" << endl;
}

cout << "erasing from v_set using v_ptr" << endl;
if (v_set.erase(v_ptr) == 0) {
cout << "didn't erase anything" << endl;
} else {
cout << "erased !" << endl;
}
}
};

BOOST_PYTHON_MODULE (test)
{
class_< Foo, shared_ptr<Foo> >("Foo")
.def("add",&Foo::add)
.def("remove",&Foo::del);

class_< Bar, shared_ptr<Bar> >("Bar");
}

编译:

%> gcc -pthread -fno-strict-aliasing -march=i686 -mtune=generic -O2 -pipe -DNDEBUG -march=i686 -mtune=generic -O2 -pipe -fPIC -I/usr/include/python2.7 -c test.cpp -o test.o

%> g++ -pthread -shared -Wl,--hash-style=gnu -Wl,--as-needed build/temp.linux-i686-2.7/test.o -L/usr/lib -lboost_python -lpython2.7 -o test.so

现在,一个小的 python 脚本:

from test import *

f = Foo()
b = Bar()

f.add(b)

f.remove(b)

结果如下:

storing 0x8c8bc58in v_set and v_ptr
deleting 0x8c8bc58
v_param == v_ptr
erasing from v_set using v_param
didn't erase anything
erasing from v_set using v_ptr
erased !
  • 我将 0x8e89c58 存储在集合内外,以防万一
  • 我将相同的引用传递给两个调用 (0x8e89c58)
  • 只是为了确保我检查是否 v == val
  • 我尝试使用 v 删除——它不起作用
  • 我尝试使用 val 删除——它有效!

我完全迷路了——看不出是什么原因造成的。任何输入?

最佳答案

我运行了您的示例,然后添加了一些我认为应该包含在 del() 中的断言:

assert(!(v_param < v_ptr));
assert(!(v_ptr < v_param));

其中一个失败了!

我深入研究了 operator< 的实现对于 boost::shared_ptr并发现了一些奇怪的东西:它比较的是引用计数而不是内部指针!一点点挖掘发现了一个 mailing list post关于这个问题的一些有用链接,指向两个 C++ 文档:N1590 解释了为什么人们认为这是一个好主意,N2637 解释了为什么不是。

似乎 Boost 人员还没有(还?)采纳 N2637 推荐,但 C++11 采纳了。所以我使用 C++11 ( g++ -std=c++0x ) 再次构建了你的测试,删除了 using namespace boost;以便使用 std::shared_ptr .这导致了一个可怕的模板错误消息,通过在顶部添加它来解决(很容易从 boost/smart_ptr/shared_ptr.hpp 派生):

template<class T> inline T * get_pointer(std::shared_ptr<T> const & p)
{
return p.get();
}

而且有效!

如果你不能使用 C++11,只需为你的集合实现你自己的自定义比较器,它可以合理地比较指针:

template <typename T>
struct SmartComparator
{
bool operator()(shared_ptr<T> const& lhs, shared_ptr<T> const& rhs) {
return lhs.get() < rhs.get();
}
};

然后这将起作用:

set< shared_ptr<Bar>, SmartComparator<Bar> > v_set;

关于c++ - boost::python 和 set::erase -> 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8203200/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com