c++ - 在回调中将 shared_ptr 转换为 void*

标签 c++

我想在接受 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;
}

最佳答案

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

我建议您在元素 结构中也放置一个共享指针。毕竟,它是共享的,因此它将延长该数据的生命周期,直到元素被删除。如果这是一个真正的 C 类型回调,您可能还希望将第一个回调参数设置为 const 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;
}

关于c++ - 在回调中将 shared_ptr 转换为 void*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18930613/

相关文章:

c++ - 如何将 "void (MyClass::*)(int)"转换为 "void (*)(int)"?

c++ - 静态方法会减少我的开销吗?

c++ - vector 分配是否会使 `reserve` 无效?

c++ - C++ 类模板的奇怪错误

c++ - Matlab计算与 'C/C++'计算..哪个效率更高?

c++ - VisualStudio 中 C++ 项目中的预编译 header 未正确链接

c++ - 运算符是什么!!在字符串上做 C++

c++ - 引用不能为 NULL 或者它可以为 NULL?

c++ - 为特定目录中除其子目录外的所有 C++ 文件生成标签文件

c++ - 获取 float 类型的参数时,Variadic C++ 函数不起作用