将shared_ptr与自定义相等运算符和STL一起使用时出现问题
将共享指针与自定义相等运算符和 std::list 一起使用时似乎存在问题。
我整理了以下示例代码来演示该问题。
在尝试编译之前:
我使用 gcc version 4.5.2 20110127
和以下命令行:
g++ -g -O0 -std=gnu++0x test.cpp
如果未启用 c++0x 功能,则源代码将无法编译。
#include<list>
#include<boost/shared_ptr.hpp>
using std::list;
using std::shared_ptr;
using std::cout;
using std::endl;
class TestInt
{
public:
TestInt(int x);
bool operator==(const TestInt& other);
private:
int _i;
};
TestInt::TestInt(int x)
{
_i = x;
}
bool
TestInt::operator==(const TestInt& other)
{
if (_i == other._i){
return true;
}
return false;
}
class Foo
{
public:
Foo(TestInt i);
shared_ptr<TestInt> f(TestInt i);
private:
list<shared_ptr<TestInt>> _x;
};
Foo::Foo(TestInt i)
{
_x.push_back(shared_ptr<TestInt>(new TestInt(i)));
};
shared_ptr<TestInt>
Foo::f(TestInt i)
{
shared_ptr<TestInt> test(new TestInt(i));
int num = _x.size();
list<shared_ptr<TestInt>>::iterator it = _x.begin();
for (int j=0; j<num; ++j){
if (test == *it){
return test;
}
++it;
}
throw "Error";
}
int main(){
TestInt ti(5);
TestInt ti2(5);
Foo foo(ti);
foo.f(ti2);
std::cout << "Success" << std::endl;
}
我本以为代码会以 Success
结束,但它却抛出了异常。
在 test
前面插入 *
以及 *it
可以解决问题,但我的理解是,当共享指针调用 __a.get 时() == __b.get()
在其 ==
运算符中应使用 TestInt
的自定义相等运算符。我不明白为什么不是。这是一个错误吗?
提前致谢。
There seems to be an issue when using shared pointers together with a custom equality operator and an std::list.
I put together the following example code to demonstrate the issue.
Before trying to compile this:
I'm using gcc version 4.5.2 20110127
with the following commandline:
g++ -g -O0 -std=gnu++0x test.cpp
The source won't compile if c++0x features aren't enabled.
#include<list>
#include<boost/shared_ptr.hpp>
using std::list;
using std::shared_ptr;
using std::cout;
using std::endl;
class TestInt
{
public:
TestInt(int x);
bool operator==(const TestInt& other);
private:
int _i;
};
TestInt::TestInt(int x)
{
_i = x;
}
bool
TestInt::operator==(const TestInt& other)
{
if (_i == other._i){
return true;
}
return false;
}
class Foo
{
public:
Foo(TestInt i);
shared_ptr<TestInt> f(TestInt i);
private:
list<shared_ptr<TestInt>> _x;
};
Foo::Foo(TestInt i)
{
_x.push_back(shared_ptr<TestInt>(new TestInt(i)));
};
shared_ptr<TestInt>
Foo::f(TestInt i)
{
shared_ptr<TestInt> test(new TestInt(i));
int num = _x.size();
list<shared_ptr<TestInt>>::iterator it = _x.begin();
for (int j=0; j<num; ++j){
if (test == *it){
return test;
}
++it;
}
throw "Error";
}
int main(){
TestInt ti(5);
TestInt ti2(5);
Foo foo(ti);
foo.f(ti2);
std::cout << "Success" << std::endl;
}
I would have expected that the code finishes with Success
but instead it throws.
Inserting a *
infront of test
as well as *it
fixes the issue but my understanding is that when the shared_ptr calles __a.get() == __b.get()
in its ==
operator it should use the custom equality operator of TestInt
. I don't understand why it is not. Is this a bug?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是因为当您比较两个
shared_ptr
时,您比较的是引用,即两个实例指向的内存地址,而不是< /em> 基础值。This is because when you compare two
shared_ptr<T>
, you are comparing the reference, that is, the memory address that the two instances point to, not the underlying values.您不是在比较 TestInt 对象,而是比较两个不同的指针,每个指针都指向自己的 TestInt 对象。所以本质上你的自定义等于运算符甚至没有被调用。
您所做的基本上是:
现在应该很明显 pi1 和 pi2 不相等,并且代码完成打印 ERROR。
(事实上,我使用原始指针而不是共享指针并没有改变任何东西,但使逻辑更容易理解。与直接使用 int 而不是使用包装类相同。)
You're not comparing TestInt objects but rather two different pointers each pointing to its own TestInt object. So essentially your custom equals operator is not even called.
What you're doing is basically:
Now it should be obvious that pi1 and pi2 are not equal and the code finishes printing ERROR.
(The fact that I have used a raw pointer instead of a shared_ptr doesn't change anything, but makes the logic easier to understand. Same with using int directly instead of using a wrapper class for it.)