2

所以我最近熟悉(并爱上了)boost 和 c++11 智能指针。它使内存管理变得更加容易。而且,最重要的是,它们通常仍然可以使用遗留代码(通过使用get调用)

但是,我一直遇到的大漏洞是多维锯齿状数组。正确的方法是使用boost::scoped_array<boost::scoped_array<double>>or vector<vector<double>>,它会很好地清理。但是,您无法double**轻松摆脱这种情况以发送到遗留代码。

有什么办法可以做到这一点,还是我坚持使用非智能锯齿状阵列?

4

2 回答 2

0

如果您使用 C++11,您可能应该使用unique_ptr<T[]>而不是scoped_array<T>. 它可以做所有可以做的事情,scoped_array然后是一些。

如果你想要一个矩形数组,我建议使用 aunique_ptr<double[]>来保存主要数据并使用 aunique_ptr<double*[]>来保存行基数。这将像这样工作:

unique_ptr<double[]> data{ new double[5*3] };
unique_ptr<double*[]> rows{ new double*[3] };
rows[0] = data.get();
for ( size_t i = 1; i!=5; ++i )
    rows[i] = rows[i-1]+3;

然后你可以传递rows.get()给一个函数double**。这种方法也适用于非矩形数组,前提是数组的几何形状在数组创建时是已知的,这样您就可以一次分配所有数据并指向rows正确的偏移量。(不过,它可能不像简单的循环那么简单。)

这也将为您提供更好的参考位置和内存使用情况,因为您只执行两次分配。您的所有数据都将一起存储在内存中,单独分配不会产生额外的开销。

如果要在创建锯齿状阵列后更改其几何形状,则需要提出一种管理存储的原则方法,以使该解决方案适用。但是,由于使用更改几何形状scoped_array很尴尬(需要特定用途swap()),如果这对您来说不是问题,我不会感到惊讶。

(请注意,这种方法也可以scoped_array与.unique_ptr<[]>unique_ptr

于 2013-07-12T21:12:28.430 回答
0

我会从std::vector<std::vector<double>>存储开始,除非结构是高度静态的。

为了生成我的数组数组,我将使用类似(作为练习留给读者的std::vector<double*>语法)对上述存储进行转换。transform_to_vector( storage, []( std::vector<double>& v ) { return v.data(); } )transform_to_vector

让两者保持同步很简单,只需将其封装在一个小类中即可。

如果锯齿状数组的大小相对固定,我会用 astd::vector<std::size_t>创建我的缓冲区(或者可能是 a std::initializer_list<std::size_t>-- 实际上是 a template<typename Container>,我只是for( : )在它上面两次,然后让调用者选择它提供给我的容器),然后std::vector<double>用大小的总和创建一个,然后std::vector<double*>在指定的偏移量处构建一个。

调整大小会变得昂贵,这是一个缺点。

使用的一个很好的特性std::vector是较新的 API 可以完全访问漂亮beginend值。如果你有一个大缓冲区,你可以将子数组的范围视图暴露给新代码(一个包含double* begin()and的结构double* end(),而我们在它的时候是double& operator[]and std::size_t size() const { return end()-begin(); }),这样他们就可以沐浴在 C++ 容器上的完整荣耀中-style 视图,同时保持对旧接口的 C 兼容性。

于 2013-07-13T01:52:05.667 回答