Issue with using shared_ptr with custom equality operator and STL
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
开发者_如何学JAVAfixes 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.
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.
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:
#include <iostream>
int main(int argc, char** argv) {
int* pi1 = new int(5);
int* pi2 = new int(5);
if (pi1 == pi2)
std::cout << "SUCCESS";
else
std::cout << "ERROR";
}
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.)
精彩评论