1

我想在接受 void* 的 C 函数中传递一个 shared_ptr。shared_ptr 中创建的对象将被销毁是否安全,何时可以销毁?喜欢,

class CBar
{
 public:
    CBar(){}
    ~CBar(){}
    void lock(){}
    void unlock(){}
};

//----------------------------------------------------

typedef struct element
{
   std::string filename;
   void (*cb)(std::string filename, void* data);
   void* data;
};

std::list<element> elm;

void reg(std::string filename, void (*cb)(std::string filename, void*data), void* data)
{
    element item;
    item.filename = filename;
    item.cb = cb;
    item.data = data;
}

void unreg(std::string filename)
{
   std::list<elements>::iter;
   for(iter=elm.begin();iter!=elm.end();++iter)
   {
      if((*iter).filename == filename)
      {
         elm.erase(iter);
         break;
      }
   }
}

void exec()
{
    std::list<element>::iterator iter;
    for(iter=elm.begin();iter!=elm.end();++iter)
    {
        (*iter).cb((*iter).filename,(*iter).data);
    }
}

//---------------------------------------------------
// in another source file

void cb(std::string filename, void* data)
{
   boost::shared_ptr<CBar> cbar = *(boost::shared_ptr<CBar>*)(data);
   cbar->lock();
}

void foo(std::string filename)
{
    //create the shared_ptr here.
    boost::shared_ptr<CBar> ffoo(new CBar);

    //then pass the shared_ptr object
    reg(filename, &cb, &ffoo);

}

int main()
{
   foo("file");
   exec();

   return 0;
}
4

1 回答 1

1

当您的函数离开作用域时,共享指针将被销毁。如果它是包装该数据的最后一个,那么数据也随之而来(因此列表中的存储也变得虚假)。您的示例更糟糕,因为您正在发送局部变量的地址,这将是完全未定义的行为reg()函数退出并且局部变量超出范围时,这将是完全未定义的行为

我建议您也将共享指针放在元素结构中。毕竟,它是共享的,因此它将延长该数据的寿命,直到元素被删除为止。如果这是一个真正的 C 类型回调,您可能还希望制作第一个回调参数 aconst char*并相应地向其发送c_str()方法。

注意:我没有安装 boost,所以下面的代码使用std::shared_ptr<>,但语义应该是一样的。

#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <memory>
#include <cstdlib>

class CBar
{
public:
    CBar(){}
    ~CBar(){}
    void lock(){}
    void unlock(){}
};

struct element
{
    std::string filename;
    void (*cb)(std::string, void* data);
    std::shared_ptr<CBar> data;
};


std::list<element> elm;

void reg(std::string filename,
         void (*cb)(std::string, void*),
         std::shared_ptr<CBar>& data)
{
    element item;
    item.filename = filename;
    item.cb = cb;
    item.data = data;
    elm.push_back(item);
}

void exec()
{
    std::list<element>::iterator iter;
    for(iter=elm.begin();iter!=elm.end();++iter)
    {
        iter->cb(iter->filename, iter->data.get());
    }
}

// in another source file
void cb(std::string filename, void* data)
{
    CBar *cbar = static_cast<CBar*>(data);
    cbar->lock();
}

void foo(std::string filename)
{
    //create the shared_ptr here.
    std::shared_ptr<CBar> ffoo(new CBar);

    //then pass the shared_ptr object
    reg(filename, &cb, ffoo);

}

int main()
{
    foo("file");
    exec();
    return 0;
}
于 2013-09-21T09:11:11.717 回答