gpt4 book ai didi

c++ - 使用 std::vector 访问由 std::unique_ptr 管理的数据

转载 作者:行者123 更新时间:2023-12-01 14:47:31 26 4
gpt4 key购买 nike

我有一个复杂的类,它包含一大块 double[2] - 由智能指针管理的类型数据,例如:std::unique_ptr<double[2]> m_data;我无法更改数据结构的类型。

我正在使用一个库,它为我提供了一个具有以下签名的函数:bool
func_in_lib(std::vector<double>& data, double& res)
.我无法更改此函数的签名。

我想传递 unique_ptr 管理的数据到期望 vector<double>& 的函数在不中断与我的复杂类(class)的联系的情况下。我希望该功能直接在我的 m_data 上工作而不是将数据复制到 std::vector<double>并将其复制回我的复杂类,因为我必须这样做很多次。

有没有办法做到这一点?

这是一些涵盖我想要的语义的代码。我关心的代码行是
vector<double> access_vec = /* give access to my_data via vector interface */;

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

//--------------------------------------------------------------------------//
//--- This function is given, I cannot change its signature.
bool
func_in_lib(std::vector<double>& data, double& res) {
//--- check some properties of the vector
if (data.size() < 10)
return false;
//--- do something magical with the data
for (auto& d : data)
d *= 2.0;
res = 42.0;
return true;
}

//--------------------------------------------------------------------------//
struct DataType {
double a = 1.0;
double b = 2.0;
double c = 3.0;
};

//--------------------------------------------------------------------------//
ostream&
operator<<(ostream& out, const DataType& d) {
out << d.a << " " << d.b << " " << d.c << endl;
return out;
}

//--------------------------------------------------------------------------//
int
main(int argc, char const* argv[]) {
int count = 20;
//--- init and print my data
unique_ptr<DataType[]> my_data = make_unique<DataType[]>(count);
for (int i = 0; i < count; ++i)
cout << my_data.get()[i];
//---
double result = 0.0;
vector<double> access_vec = /* give access to my_data via vector interface */;
func_in_lib(access_vec, result);

return 0;
}

最佳答案

tl; dr:不可能以符合标准的方式。

这实际上几乎是可能的,但是 std::allocator限制挡住了你的去路。让我解释。

  • 一个 std::vector “拥有”它用于元素存储的内存: vector 有权 delete[]内存(例如,在销毁时,或在移动后销毁,或 .resize()push_back 等)并在其他地方重新分配。如果您想保留 unique_ptr 的所有权,你不能允许这种情况发生。虽然你的 func_in_lib() 的模拟实现是真的没有做任何事情 - 你的代码不能做出这些假设,因为它必须迎合函数的声明,而不是它的主体。

  • 但是假设您愿意稍微改变规则,并假设 vector 在运行时不会替换其分配的内存。这是合法的,从某种意义上说 - 如果您能够传递内存以供 vector 以某种方式使用,并且它替换了内存区域,您可以检测到当 func_in_lib()返回,然后要么修复 unique_ptr 中的内容,要么抛出异常(取决于代码中的其他位置是否包含指向废弃内存的指针)。或者——假设 func_in_lib()拍了 const std::vector<double[2]>&而不是非常量引用。我们的路还是会被堵死。为什么?
  • std::vector通过分配器对象管理内存。分配器是一个模板,所以理论上你可以使用一个 vector ,分配器可以做任何你想做的事情 - 例如,从预先分配的内存(你给它 - 从 unique_ptr::get() 开始,并拒绝重新分配任何内存,例如,通过抛出异常。由于 std::vector 构造函数之一采用适当类型的分配器 - 您可以构造所需的分配器,用它创建一个 vector ,然后传递对该 vector 的引用。

  • 但是很可惜——你的图书馆太残忍了。 func_in_lib没有模板化,只能为其分配器采用默认模板参数: std::allocator .
  • std::vector 使用的默认分配器和其他标准库容器是 std::allocator .现在,在我看来,分配器通常是一个错误的想法。但是 std::allocator特别烦人。具体来说,它不能使用预先存在的内存区域来构建它以供它使用;它只保存它自己分配的内存——从不保存你给它的内存。

  • 所以,你永远不会得到 std::vector使用你想要的内存。

    那么该怎么办?
  • 选项1:你的黑客:
  • 弄清楚 std::vector 的具体布局在您的系统上
  • 手动将字段值设置为有用的值
  • 使用reinterpret_cast<std::vector>()在您的原始数据上。
  • 选项 2:malloc()free()钩子(Hook)(如果您在类 Unix 系统上和/或使用使用 libc 的编译器)
  • 见:Using Malloc Hooks

    这个想法是检测 new[]来自 std::vector 的电话你创造,并给它你自己的unique_ptr -控制内存而不是实际分配任何东西。当 vector 要求释放内存时(例如在销毁时),你什么也不做。
  • 切换库。图书馆暴露func_in_lib写得不好。除非它是一个非常利基的库,否则我相信会有更好的选择。事实上,你可以更好地自己编写它。
  • 不要在库中使用该特定功能;坚持使用库中较低级别的简单原语并实现 func_in_lib()使用那些。并不总是可行的,但可能值得做空。
  • 关于c++ - 使用 std::vector<double> 访问由 std::unique_ptr<double[2]> 管理的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62467215/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com