【问题标题】:Issue with using shared_ptr with custom equality operator and STL将 shared_ptr 与自定义相等运算符和 STL 一起使用的问题
【发布时间】:2024-01-30 05:05:01
【问题描述】:

将共享指针与自定义相等运算符和 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 前面插入* 可以解决问题,但我的理解是,当shared_ptr 在其== 运算符中调用__a.get() == __b.get() 时,它应该使用@987654330 的自定义相等运算符@。我不明白为什么不是。这是一个错误吗?

提前致谢。

【问题讨论】:

  • 使用编辑器中的{}按钮来格式化代码。

标签: c++ c++11 shared-ptr comparison-operators


【解决方案1】:

这是因为比较两个shared_ptr&lt;T&gt;时,是比较reference,即两个实例指向的内存地址,不是底层价值观。

【讨论】:

  • 不正确。正如我在帖子中指出的,shared_ptr 默认比较 __a.get() == __b.get,原则上应该比较底层对象。如果我不使用 std::list 例如,它实际上会这样做。但在这种情况下它失败了。
  • shared_ptr::get() 返回指向被引用对象的指针,而不是对它的引用。 DeadMG 的答案是正确的。
  • 对不起,我的错。将 em 与基于策略的 smart_ptr (axter.com/smartptr/classsmart__ptr.htm) 混淆了,默认值是 value_comparsion_semantic_policy。
【解决方案2】:

您不是在比较 TestInt 对象,而是比较两个不同的指针,每个指针都指向它自己的 TestInt 对象。所以基本上你的自定义等于运算符甚至没有被调用。

你所做的基本上是:

#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 不相等,代码完成打印 ERROR。

(我使用原始指针而不是 shared_ptr 的事实并没有改变任何东西,但使逻辑更容易理解。直接使用 int 而不是为其使用包装类。)

【讨论】:

    最近更新 更多