c++ - 避免手动创建 lambda 来包装对 new[]: 的调用,以用作 std::generate 中的生成器函数

标签 c++ lambda c++17 new-operator stl-algorithm

简短版本

目前,我为 new [] 手动创建了一个 lambda 函数。 ,如下:

[](){ return new double[3]; }

此 lambda 稍后在对 std::generate 的调用中用作生成器函数:

std::generate(vec.begin(), vec.end(), [](){ return new double[3]; });

我可以避免创建这个 lambda 并使用一些更标准的功能/语法糖/替代品吗? C++17优先;但是,如果 C++20(或某些提案)提供更好的东西,我也很感兴趣。

长版本提供了一些背景知识,以及类似情况的现有解决方案,当 for_each 时用于释放内存。


带背景的长版

需要

  1. 创建std::vector存储 double*指针,指向固定大小的一维数组。
  2. 将此结构传递给库函数,库函数将用数据填充它。
  3. 使用填充的数据。
  4. 清除分配的内存。

条件

  • 由于(2),我无法控制库函数的参数类型;因此,我只能使用 std::vector<double*>不管其他容器如何更适合。
  • 想要干净、简约且高效的代码
  • 特别是,我从简单的普通 for 开始-循环并决定去 STL <algorithm> .

初始代码

#include <vector>

int main()
{
    // (1)
    size_t numElems = 10;
    std::vector<double*> vec(numElems);
    for (size_t i=0; i<numElems; i++)
    {
        vec[i] = new double[3];
    }

    // (2)-(3) SOME ACTIVITY with vec

    // (4)
    for (size_t i=0; i<numElems; i++)
    {
        delete [] vec[i];
    }
}

为了简单起见,我对 numElems 进行了硬编码在 vector vec ,并使用 double* 的硬编码大小数组为 3 。跳过 (2)–(3) 中传递给外部函数和事件的过程。此代码有效。

新代码

我尝试了以下方法:

#include <vector>
#include <algorithm>
#include <memory>

int main()
{
    // (1)
    size_t numElems = 10;
    std::vector<double*> vec(numElems);
    std::generate(vec.begin(), vec.end(), [](){ return new double[3]; });

    // (2)-(3) SOME ACTIVITY with vec

    // (4)
    std::for_each(vec.begin(), vec.end(), std::default_delete<double[]>());
}

这也很好用。

问题

修改后的版本中,通过 std::default_delete<> 进行删除。通过 std::for_each 申请方便地提供语言关键字 delete [] 的“函数表示” (措辞有点草率)。

是否有类似的方式“表示”new [] ?或者我是否坚持手动创建 lambda 以用作 std::generate 的生成器函数参数?

最佳答案

单个堆分配的内存开销相当于每个元素的几个指针。因此,如果您正在处理一个巨大的指针 vector ,那么使用单个分配和一个 vector 作为 View 可能会节省内存:

struct vector3 {
    vector3(size_t numElements) 
        // use new[] over std::make_unique to avoid value initialization,
        // since it's assumed the library function will initialize the data
        : storage(new std::array<double, 3>[numElements]) {
        view.reserve(numElements);
        std::transform(
            storage.get(), 
            storage.get() + numElements, 
            std::back_inserter(view),
            [](auto& a) { return a.data(); }); // no good substitute for lambda here
    }
    std::unique_ptr<std::array<double, 3>[]> storage;
    std::vector<double*> view;
};

用法:

vector3 myVector(10);
library_function(myVector.view);

演示:https://godbolt.org/z/6x4PEs

编辑:进入类以保证每个 Swift 的生命周期 - Friday Pie 的建议。

关于c++ - 避免手动创建 lambda 来包装对 new[]: 的调用,以用作 std::generate 中的生成器函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64330071/

相关文章:

c++ - Linux下有没有C++的用户态多线程库/框架?

c++ - 具有相同签名和捕获的常见 lambda 类型

c++ - 在可移动类型的构造函数 lambda 中安全使用 captured this

c++ - 如何在 CMake 中启用 C++17

c++ - 静态变量,单独编译

c++ - 如何使用 C++ 打开 %appdata% 中的文件夹?

c++ - C++11 中 unique_ptr 的延迟初始化

c++ - 参数列表中没有 "const"无法编译 lambda

c++ - 通过 lambda 定义的 constexpr 递归函数

c++ - 什么是 string_view?