无法将 shared_ptr 参数传递给函数指针

Cannot pass shared_ptr argument to function pointer

我对使用带有 shared_ptr 参数的函数指针的代码有疑问。

这是示例代码。

header.h

#include <functional>
#include <iostream>
template <class T> class FuncWrapper{
    private:
        void (*original_function)(T a);
    public:
        void setFunction(void *func);
        void execFunction(T a, void *data);
};

template <class T> void FuncWrapper<T>::setFunction(void *func){
    original_function = (void (*)(T))func;
}

template <class T> void FuncWrapper<T>::execFunction(T a, void *data){   
    FuncWrapper<T>* wrapper = (FuncWrapper<T>*)data;
    std::cout << "inside wrapper " << *(a.get()) << std::endl;
    wrapper->original_function(a);
}

main.cpp

#include <iostream>
#include <memory>
#include "header.h"

class ClassA{
    public:
        ClassA(std::shared_ptr<int> a){
            FuncWrapper<std::shared_ptr<int>> *fw;
            fw = new FuncWrapper<std::shared_ptr<int>>;
            fw->setFunction((void*)&ClassA::print_int);
            std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
            g(a);
            delete fw;
        }
    private:
        void print_int(std::shared_ptr<int> x) {
            std::cout << "printing int" << std::endl;
            std::cout << "given int " << *(x.get()) << std::endl;
        }
};

int main(int argc, char * argv[]){
    std::shared_ptr<int> x = std::make_shared<int>(10);
    std::cout << "inside main " << *(x.get()) << std::endl;
    ClassA *temp;
    temp = new ClassA(x);
    delete temp;
    return 0;
}

结果

inside main 10
inside wrapper 10
printing int
Segmentation fault (core dumped)

我不明白为什么它会导致分段错误。

std::shared_ptr<int> 更改为 int 效果很好。
因此我假设它与shared_ptr的ownership有关,但我不熟悉智能指针,我完全不知所措。

我想知道

限制是

其他情况随意更改。 (在 ClassA 构造函数内部,在 main execFunction 等内部)

问题不在于 shared_ptr,而是指向函数和成员函数的指针不匹配。

您的函数包装器需要一个指向函数的指针 (void (*)(std::shared_ptr<int>)),但您提供了一个指向成员函数 (void (ClassA::*)(std::shared_ptr<int>)) 的指针,这是不同的。添加了一个指向 this 的指针的隐式前导参数。

真实情况是这样的:

// pointer to member function
void (*)(ClassA *ptr, std::shared_ptr<int>)

您的 shared_ptr 转到第一个参数,幸运的是应用程序段错误。

其中一个解决方案是使函数 print_int 静态化。

class ClassA{
    public:
        ClassA(std::shared_ptr<int> a){
            FuncWrapper<std::shared_ptr<int>> *fw;
            fw = new FuncWrapper<std::shared_ptr<int>>;
            fw->setFunction((void*)&ClassA::print_int);
            std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
            g(a);
            delete fw;
        }

    private:
        static void print_int(std::shared_ptr<int> x) {
            std::cout << "printing int" << std::endl;
            std::cout << "given int " << *(x.get()) << std::endl;
        }
};

但是您的代码中似乎还有另一个问题。函数指针不应转换为对象指针(void * 是)。也许可以这样更改您的 setFunction:

void setFunction(void (*func)(T)) {
        original_function = func;
}

更多相关信息here