在类中将智能指针与Tensorflow C API对象一起使用 输出

问题描述

我想在智能指针中使用具有特定删除器和构造函数的对象。

该对象称为:TF_Status-它是使用TF_NewStatus()函数创建的,并使用TF_DeleteStatus()函数删除的。

当我想将其与智能指针一起使用时,我将像这样初始化它:

std::unique_ptr<TF_Status,void(*)(TF_Status*)> status(TF_NewStatus(),TF_DeleteStatus);

但是,当我想将其用作类成员时,我不想在c'tor中创建对象,因为我必须先设置一些值。问题是这种智能指针没有认值。

你们有什么解决办法吗?

解决方法

如果我理解正确,则需要这样的东西:

struct some_t
{
    some_t()
        : m_status(nullptr,TF_DeleteStatus)
    {}
    void later()
    {
        m_status.reset(TF_NewStatus());
    }
    std::unique_ptr<TF_Status,void(*)(TF_Status*)> m_status;
};

unique_ptr在构造时变为零指针。稍后,您可以创建TF_Status对象。

,

您可以先实例化具有空指针的unique_ptr,然后使用实际的TF_Status重置该指针:

#include <iostream>

// TF_*
struct TF_Status {};
TF_Status* TF_NewStatus() { std::cout << "\tNew TF_Status\n" ; return new TF_Status(); }
void TF_DeleteStatus(TF_Status* s) { std::cout << "\tDelete TF_Status\n"; delete s; }

#include <memory>

class C
{
    std::unique_ptr<TF_Status,decltype(TF_DeleteStatus)*> status;
public:
    C() : status(nullptr,TF_DeleteStatus) {}
    void acquire_status() {
        status.reset(TF_NewStatus());
    }
};

// test

int main()
{
    std::cout << "About to instantiate a C\n";
    C c;
    std::cout << "done\n";
    
    std::cout << "About to acquire_status\n";
    c.acquire_status();
    std::cout << "done\n";
}

输出

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
About to instantiate a C
done
About to acquire_status
  New TF_Status
done
  Delete TF_Status

请注意,std::unique_ptr::reset

给出current_ptr管理的指针*this,按此顺序执行以下操作:

  1. 保存当前指针old_ptr = current_ptr的副本
  2. 使用参数current_ptr = ptr覆盖当前指针
  3. 如果旧指针为非空,则删除先前管理的对象if(old_ptr) get_deleter()(old_ptr)

因此,即使您的智能指针在其上调用TF_Status时,即使智能指针包含实际的reset(),也可以保证安全。

demo

,

我建议创建一个删除器类:

struct TF_Status;
void TF_DeleteStatus(TF_Status*);

struct TF_StatusDeleter { 
    void operator()(TF_Status* s) noexcept { TF_DeleteStatus(s); } 
};

然后:

using TF_StatusPtr = std::unique_ptr<TF_Status,TF_StatusDeleter>;

这样TF_StatusPtr可以被默认初始化(无需在构造函数中显式初始化此成员)和sizeof(TF_StatusPtr) == sizeof(TF_Status*)std::unique_ptr对删除程序使用空的基类优化,因此没有数据成员的TF_StatusDeleter子对象占用0个字节。

std::unique_ptr<TF_Status,void(*)(TF_Status*)>的大小是原来的两倍,因为每个实例都存储指向同一TF_DeleteStatus函数的指针,这很浪费。