自动释放外部api分配的对象

时间:2014-04-17 14:50:37

标签: c++ memory-management c++11

我有一个Visual Studio 2013 C ++ 11程序,我需要使用一个在数组中分配大量字符缓冲区的API:

int main(int argc, char* argv[])
{
    char* names[10] = {};
    unsigned int count = _countof(names);
    some_external_api_to_get_values(count, names, &count);
    // do something with the names array...
    for (unsigned int i = 0; i < count; ++i)
        release_objects(names[i]);
    return 0;
}

我希望在销毁时自动释放对象。所以我添加了这个类,但是我遗漏了一些允许编译器在这个类和它期望的char **类型之间进行转换的东西。

template<typename T>
class release_objects_on_destruction : private boost::noncopyable
{
public:
    explicit release_objects_on_destruction(T* p) : p_(p) { };
    release_objects_on_destruction() : p_(nullptr) { };
    ~release_objects_on_destruction() { if (p_) release_objects(p_); };
    T** operator&() { return &p_; };
    operator T*() const { return p_; };    
    operator const T*() const { return p_; };
private:
    T* p_;
};

int main( int argc, char* argv[])
{
    release_objects_on_destruction<char> names[10];
    unsigned int count = _countof(names);
    // error C2664: 'int some_external_api_to_get_values(unsigned int,char**,unsigned int*)' : cannot convert argument 2 from 'release_objects_on_destruction<char> [10]' to 'char**'
    some_external_api_to_get_values(count, names, &count);
    return 0;
}

我错过了什么转换操作符?

1 个答案:

答案 0 :(得分:1)

它不起作用,因为您的API处于错误的级别。您需要将external_api调用和release_objects调用封装到同一对象中。这就是你当前的包装器失败的原因。

class api_wrapper {
    static const object_count = 10;
    std::array<char*, object_count> objects;
    unsigned count = object_count;
public:
    api_wrapper() {
        some_external_api_to_get_values(count, objects.data(), &count);
    }
    // example accessors
    char** data() { return objects.data(); }
    unsigned count() { return count; }

    api_wrapper(api_wrapper&& other)
        : objects(other.objects), count(other.count)
    {
        other.count = 0;
    }
    api_wrapper(const api_wrapper&) = delete;
    ~api_wrapper() {
        for (unsigned int i = 0; i < count; ++i)
            release_objects(objects[i]);
    }
};