Проблема с использованием shared_ptr с пользовательским оператором равенства и STL - PullRequest
1 голос
/ 19 марта 2011

Кажется, есть проблема при использовании общих указателей вместе с пользовательским оператором равенства и 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, но вместо этого он выдает.

Вставка * infront test, а также *it устраняет проблему, но я понимаю, что когда shared_ptr вызывает __a.get() == __b.get() в своем операторе ==, он должен использовать пользовательский оператор равенства TestInt. Я не понимаю, почему это не так. Это ошибка?

Заранее спасибо.

Ответы [ 2 ]

10 голосов
/ 19 марта 2011

Это связано с тем, что при сравнении двух shared_ptr<T> вы сравниваете ссылку , то есть адрес памяти, на который указывают два экземпляра, , а не базовые значения.

3 голосов
/ 19 марта 2011

Вы сравниваете не объекты TestInt, а два разных указателя, каждый из которых указывает на свой собственный объект TestInt.Таким образом, ваш пользовательский оператор equals даже не вызывается.

То, что вы делаете, в основном:

#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";
}

Теперь должно быть очевидно, что pi1 и pi2 не равны, и код завершаетсяprint ERROR.

(Тот факт, что я использовал необработанный указатель вместо shared_ptr, ничего не меняет, но облегчает понимание логики. То же самое с непосредственным использованием int вместо использования класса-оболочки для него.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...