我可以在堆分配的原始数组上使用std :: sort吗?

时间:2019-05-13 15:57:47

标签: c++ sorting memory-management heap-memory dynamic-arrays

我们知道,当使用连续的内存块时,我们可以轻松地获得一个迭代器(此处为&arra[0]arra),并将迭代器传递给std :: sort。

例如:

int arra[100];
    for (int i = 0; i < 100; i++) {
        arra[i] = rand() % 32000;
    }
    for (int i = 0; i < len; i++)std::cout << arra[i]<<" ";
    std::sort(arra,arra+100);

现在,如果我有一个分配堆的数组,例如这里的arr

int len;
    len = 100;
    int* arr = new int[len];
    for (int i = 0; i < len; i++) {
        arr[i] = rand() % 32000;
    }

我不知道是否可以为此数组获得迭代器,所以我可以完全为该数组使用std :: sort吗? 如果没有,在这样的数组上使用std :: sort有什么解决方法吗?

4 个答案:

答案 0 :(得分:8)

指针确实符合RandomAccessIterator所要求的std::sort标准。只要它们指向同一(连续)数组,它们是否指向堆栈内存或堆内存都没有关系。所以您可以简单地使用:

std::sort(arr, arr + len);

这就是说,std::vector可能是在堆上分配数组的更好选择。它将使您免于自己管理内存的麻烦。

答案 1 :(得分:3)

是的,您可以在两种情况下以相同的方式使用std::sortstd::sort不知道或不在乎内存的分配方式。

答案 2 :(得分:2)

在C ++库中,迭代器基本上是花式指针。因此,将指针增加到数组的末尾以获取“ end”指针是符合标准的:

#include<algorithm>
#include<iostream>

int main() {
    int len;
    len = 100;
    int* arr = new int[len];
    for (int i = 0; i < len; i++) {
        arr[i] = rand() % 32000;
    }
    //Valid, Defined Behavior that works as expected
    std::sort(arr, arr + len);
    //alternative, to make the code easier to read:
    //auto begin = arr;
    //auto end = arr + len;
    //std::sort(begin, end);
    for(int i = 0; i < len; i++)
        std::cout << arr[i] << std::endl;
}

但是,某些编译器(如Visual Studio的编译器)认识到这种代码本质上是不安全的,因为您需要手动提供数组的长度。结果,如果尝试这样做,它们将导致(如果需要,可使用Compiler标志抑制)编译时错误,并建议您改用编译器提供的实用程序:

#include<algorithm>
#include<iostream>

int main() {
    int len;
    len = 100;
    int* arr = new int[len];
    for (int i = 0; i < len; i++) {
        arr[i] = rand() % 32000;
    }

    //MSVC Specific Code!
    auto begin = stdext::make_checked_array_iterator(arr, len);
    auto end = arr + len;
    std::sort(begin, end);
    for(int i = 0; i < len; i++)
        std::cout << arr[i] << std::endl;
}

有关Visual Studio编译器这一特殊功能的更多信息,请参见:https://docs.microsoft.com/en-us/cpp/standard-library/checked-iterators?view=vs-2019

答案 3 :(得分:1)

  

我可以在堆分配的原始数组上使用std :: sort吗?

是的

  

我不知道是否可以为此数组获得迭代器

可以。

指向元素的指针是数组的随机访问迭代器。对于自动数组,数组名称隐式衰减为一个指针,您可以将其用作数组开头的迭代器。对于动态数组,new[]的结果已经是指针,即指向数组开头的迭代器。就像您的示例一样,您可以使用指针算术将指针指向末尾。

关于使用std::sort,数组变量和指向动态数组的指针之间唯一的显着区别是,不能像使用指针一样将std::endstd::size与指针一起使用与数组变量。相反,您需要单独知道数组的大小。在这种情况下,您已将长度存储在变量len中。