有没有办法在数组上遍历shared_或任何"smart" ptr?

Is there a way to traverse shared_ or any "smart" ptr over an array?

本文关键字:任何 smart ptr shared 数组 遍历 有没有      更新时间:2023-10-16

据我所知,智能指针应该与"原始"指针相等,不同之处在于它是安全的。好的,但如果我有常规指针:

int* p = new int[10];
fill(p, p + 10, 0);//this will work for regular pointer but not for smart one.  

与手写循环相同:

for(int i = 0; i < 10; ++i)
{
*p[i] = 0;
}

这对聪明的创业者来说是不可能的。所以问题是,我如何初始化我存储在其中一个智能指针中的指针的数组(假设为shared_ptr)?

首先,使用std::vector<int>可能更容易。不过,如果您的数组大小不变,那么std::vector<int>确实可以用智能指针来代替。

这样一来,您的第一选择应该是std::unique_ptr,特别是数组专用化:std::unique_ptr<int[]>。(如果不这样做,智能指针将在指针上使用delete而不是delete[],从而导致未定义的行为。)您的代码将变为:

std::unique_ptr<int[]> p(new int[10]);
std::fill(p.get(), p.get() + 10, 0);

正如您所看到的,智能指针有一个返回底层指针的get()方法。

从这里开始,如果你需要使用std::shared_ptr,事情就会变得非常危险(据我所知,要注意不幸的疏忽)。这种疏忽是std::shared_ptr没有阵列专业化:

{
    std::shared_ptr<int> x(new int[10]);
} // oops! calls delete x.get(); instead of delete [] x.get(); ... UB!

然而,std::shared_ptr可以很容易地纠正这种情况,比如:

{
    std::shared_ptr<int> x(new int[10], std::default_delete<int[]>());
} // correctly uses delete [] x.get()

从这一点来看,代码是相同的:

std::shared_ptr<int> p(new int[10], std::default_delete<int[]>());
std::fill(p.get(), p.get() + 10, 0);

请注意,std::shared_ptr提供了一个从std::unique_ptr构造的构造函数,该构造函数正确地使用了deleter。所以这是安全的:

std::unique_ptr<int[]> p(new int[10]);
std::shared_ptr<int> p2(std::move(p)); // okay, uses std::default_delete<int[]>()

假设您使用如下智能指针声明数组:

boost::shared_array<int> p = new int[10];

fill-函数的调用将如下所示:

fill(p.get(), p.get() + 10, 0);

p.get()返回由智能指针管理的原始指针。你的循环不需要调整,但它首先是错误的:

for(int i = 0; i < 10; ++i) {
    p[i] = 0; // no dereferencing required here
}