c++ make_shared<> 二维数组
c++ make_shared<> with 2d array
在处理2d数组分配时使用简单的指针是通过new以这种方式完成的(假设矩阵10x1000):
double ** dPtr ;
dPtr = new double* [10] ;
for( size_t i =0 ; i<10 ; i++ ){
dPtr[i] = new double [1000] ;
}
现在,当使用智能指针时,我们可以定义矩阵类型(假设使用shared_ptr
)为
std::shared_ptr<std::shared_ptr<double[]>[]> dPtr ;
如何使用 make_shared<>
执行相同分配的正确语法?
我不会多次调用 new,而是一次分配一个大缓冲区:double* array = new double[10 * 1000];
。当然这取决于你想要什么样的数据结构。单个缓冲区将具有更好的缓存局部性并且可能更快,但这取决于您的要求。
此外,您正在做的是为矩阵中的每一行添加一个 shared_ptr
- 这就是您想要的吗?用一个 shared_ptr 来管理整个矩阵可能会更好:
std::shared_ptr<double[]> array (new double[10*1000]);
如果你真的想要,你也可以在每一行中添加一个 shared_ptr:
std::shared_ptr<std::shared_ptr<double[]>[]> array2(
new std::shared_ptr<double[]>[10]);
for (int i = 0; i < 10; i++)
{
array2[i] = std::shared_ptr<double[]>(new double[1000]);
}
将您的代码直接翻译成 std::make_shared()
看起来像这样:
std::shared_ptr<std::shared_ptr<double[]>[]> dPtr;
dPtr = std::make_shared<std::shared_ptr<double[]>>(10);
for( size_t i = 0 ; i < 10 ; i++ ){
dPtr[i] = std::make_shared<double[]>(1000);
}
可以进一步清理一下,例如:
using double_ptr_1D = std::shared_ptr<double[]>;
using double_ptr_2D = std::shared_ptr<double_ptr_1D[]>;
double_ptr_2D dPtr = std::make_shared<double_ptr_1D>(10);
for( double_ptr_1D &elem : dPtr ){
elem = std::make_shared<double[]>(1000);
}
甚至:
using double_ptr_1D = std::shared_ptr<double[]>;
auto dPtr = std::make_shared<double_ptr_1D>(10);
for( auto &elem : dPtr ){
elem = std::make_shared<double[]>(1000);
}
现在,话虽如此,直到 C++17 才将数组支持添加到 std::shared_ptr
,直到 C++20 才添加到 std::make_shared()
。因此,如果您使用的是 C++17,则必须使用 new[]
手动构建数组,例如:
using double_ptr_1D = std::shared_ptr<double[]>;
using double_ptr_2D = std::shared_ptr<double_ptr_1D[]>;
double_ptr_2D dPtr( new double_ptr_1D[10] );
for(size_t i = 0; i < 10; ++i){
dPtr[i] = double_ptr_1D( new double[1000] );
}
但是,如果您使用的是 C++11 或 C++14,那么您就不走运了,因为您根本无法对数组使用 std::shared_ptr
。 std::unique_ptr
在 C++11 中具有数组支持,在 C++14 中 std::make_unique()
也是如此,但是 std::unique_ptr
没有 reference-counting 语义 std::shared_ptr
已。如果你真的需要它,你将不得不手动实现你自己的引用计数。
在处理2d数组分配时使用简单的指针是通过new以这种方式完成的(假设矩阵10x1000):
double ** dPtr ;
dPtr = new double* [10] ;
for( size_t i =0 ; i<10 ; i++ ){
dPtr[i] = new double [1000] ;
}
现在,当使用智能指针时,我们可以定义矩阵类型(假设使用shared_ptr
)为
std::shared_ptr<std::shared_ptr<double[]>[]> dPtr ;
如何使用 make_shared<>
执行相同分配的正确语法?
我不会多次调用 new,而是一次分配一个大缓冲区:double* array = new double[10 * 1000];
。当然这取决于你想要什么样的数据结构。单个缓冲区将具有更好的缓存局部性并且可能更快,但这取决于您的要求。
此外,您正在做的是为矩阵中的每一行添加一个 shared_ptr
- 这就是您想要的吗?用一个 shared_ptr 来管理整个矩阵可能会更好:
std::shared_ptr<double[]> array (new double[10*1000]);
如果你真的想要,你也可以在每一行中添加一个 shared_ptr:
std::shared_ptr<std::shared_ptr<double[]>[]> array2(
new std::shared_ptr<double[]>[10]);
for (int i = 0; i < 10; i++)
{
array2[i] = std::shared_ptr<double[]>(new double[1000]);
}
将您的代码直接翻译成 std::make_shared()
看起来像这样:
std::shared_ptr<std::shared_ptr<double[]>[]> dPtr;
dPtr = std::make_shared<std::shared_ptr<double[]>>(10);
for( size_t i = 0 ; i < 10 ; i++ ){
dPtr[i] = std::make_shared<double[]>(1000);
}
可以进一步清理一下,例如:
using double_ptr_1D = std::shared_ptr<double[]>;
using double_ptr_2D = std::shared_ptr<double_ptr_1D[]>;
double_ptr_2D dPtr = std::make_shared<double_ptr_1D>(10);
for( double_ptr_1D &elem : dPtr ){
elem = std::make_shared<double[]>(1000);
}
甚至:
using double_ptr_1D = std::shared_ptr<double[]>;
auto dPtr = std::make_shared<double_ptr_1D>(10);
for( auto &elem : dPtr ){
elem = std::make_shared<double[]>(1000);
}
现在,话虽如此,直到 C++17 才将数组支持添加到 std::shared_ptr
,直到 C++20 才添加到 std::make_shared()
。因此,如果您使用的是 C++17,则必须使用 new[]
手动构建数组,例如:
using double_ptr_1D = std::shared_ptr<double[]>;
using double_ptr_2D = std::shared_ptr<double_ptr_1D[]>;
double_ptr_2D dPtr( new double_ptr_1D[10] );
for(size_t i = 0; i < 10; ++i){
dPtr[i] = double_ptr_1D( new double[1000] );
}
但是,如果您使用的是 C++11 或 C++14,那么您就不走运了,因为您根本无法对数组使用 std::shared_ptr
。 std::unique_ptr
在 C++11 中具有数组支持,在 C++14 中 std::make_unique()
也是如此,但是 std::unique_ptr
没有 reference-counting 语义 std::shared_ptr
已。如果你真的需要它,你将不得不手动实现你自己的引用计数。