在给定的迭代次数后使用 RAII 重新分配资源

Using RAII to re-allocate a resource after a given number of iterations

我需要处理大量项目。为此,需要一个资源,在本例中是一个外部软件程序。

由于外部软件的内存泄漏,无法使用单个资源实例处理所有项目。出于性能原因,创建资源的新实例不是一个选项。因此,我需要处理给定大小 N 的部分项目。这意味着我创建资源实例,处理接下来的 N 个项目,然后释放资源。重复此过程,直到处理完所有项目。

物品的处理实际上是一个复杂的过程,可能会导致不同类型的故障(异常)。因此我喜欢使用 RAII 习惯用法来管理资源并确保每个实例都被干净地释放。

用两个嵌套循环实现这个没什么大不了的,如本例所示:

#include <iostream>
#include <vector>

class ResourceAllocator {
public:
    ResourceAllocator() { std::cout << "Allocating resource\n"; }
    ~ResourceAllocator() { std::cout << "Deallocating resource\n"; }
    void Process(int n) { std::cout << "Processing item " << n << "\n"; }
};

int main()
{
    const int totalSize = 20;
    const int portionSize = 6;

    std::vector<int> items(totalSize);
    int count = 0;
    bool complete = false;
    while (!complete) {
        ResourceAllocator a;
        for (int i = 0; i < portionSize; i++) {
            a.Process(items[i]);
            count++;
            if (count >= totalSize) {
                complete = true;
                break;
            }
        }
    }
}

但是我一直想知道是否有只需要一个循环的解决方案。

I create an instance of the resource, process the next N items, then deallocate the resource. This process is repeated until all items have been processed.

您可以使用移动语义 来转移资源的所有权。当遵循 RAII 习语的对象是移动分配的目标时,它会释放它拥有的资源(如果有的话)并取得分配给它的资源的所有权——分配操作的来源:

Resource r(/* 1st resource */);
// ...
r = Resource(/* 2nd resource */);

分配应释放 r 拥有的资源并获得正在创建的新资源的所有权(即 Resource(/* 2nd resource */))。

您应该为您的 class 实施 move assignment operator。当对象被处理后,你使用这些对象作为移动分配的目标。

另一种方法是为值使用一个容器,并在每 N 次迭代后重置它。

#include <iostream>
#include <vector>
#include <optional>

class ResourceAllocator {
public:
    ResourceAllocator() { std::cout << "Allocating resource\n"; }
    ~ResourceAllocator() { std::cout << "Deallocating resource\n"; }
    void Process(int n) { std::cout << "Processing item " << n << "\n"; }
};

int main()
{
    const int totalSize = 20;
    const int portionSize = 6;

    std::vector<int> items(totalSize);
    {
        std::optional<ResourceAllocator> a;
        for (int i = 0; i < items.size(); ++i)
        {
            if (i % portionSize == 0) a.emplace();

            a->Process(items[i]);
        }
    }
}