简体   繁体   English

是否可以在std :: unique上应用std :: sort <T[ ]> ?

[英]Is it possible to apply std::sort on std::unique<T[ ]>?

Suppose I have a dynamic array that I want to sort, I could do 假设我有一个我要排序的动态数组,我可以做

std::vector<int> v(100);
for (int i = 0; i < 100; i++) v[i] = rand();
std::sort(v.begin(), v.end());

but for performance critical code, the initialization overhead is unacceptable, more details at https://stackoverflow.com/a/7269088/3667089 但对于性能关键代码,初始化开销是不可接受的,更多细节请访问https://stackoverflow.com/a/7269088/3667089

I could also do 我也可以

int *v = new int[100];
for (int i = 0; i < 100; i++) v[i] = rand();
std::sort(v, v + 100);

but having to manage memory ourselves is bound to memory leak in large codebases. 但是必须自己管理内存必然会在大型代码库中发生内存泄漏。

So it seems that the most feasible approach is 所以似乎最可行的方法是

std::unique_ptr<int[]> v(new int[100]);
for (int i = 0; i < 100; i++) v[i] = rand();
std::sort(v, v + 100);

No initialization overhead nor need to worry about memory management, but this returns a long compilation error. 没有初始化开销也不需要担心内存管理,但这会返回一个很长的编译错误。 Could someone let me know what I am doing wrong? 有人能让我知道我做错了什么吗?

I am on Ubuntu 14.04, GCC as compiler. 我在Ubuntu 14.04,GCC作为编译器。

EDIT: Change the code so the data is not already sorted 编辑:更改代码,以便数据尚未排序

std::sort still needs iterators, and unique_ptr is not an iterator. std::sort仍然需要迭代器,而unique_ptr不是迭代器。 However, it does hold onto something that can be used as one: its pointer: 但是,它确实保留了可以用作一个的东西:它的指针:

std::sort(v.get(), v.get() + 100);

or 要么

std::sort(&*v, &*v + 100);

or 要么

std::sort(&v[0], &v[0] + 100); // N.B. &v[100] invokes undefined behavior

But what you really want is a vector allocator that default-initializes instead of value-initializes. 但你真正想要的是一个vector分配器,它默认初始化而不是值初始化。 That's where the performance difference is coming from - using std::vector with the default allocator will zero-initialize all your int s first and then assign them some value, whereas your other options do not have this extra zero-initialization step. 这就是性能差异的来源 - 使用带有默认分配器的std::vector将首先对所有int零初始化,然后为它们分配一些值,而其他选项则没有这个额外的零初始化步骤。

Check out Casey's implementation of such a thing and then just do: 查看Casey实现这样的事情,然后做:

std::vector<int, default_init_allocator<int>> v(100); // not zero-initialized
for (int i = 0; i < 100; i++) v[i] = i;
std::sort(v.begin(), v.end());

A different approach which is simpler in the sense that you don't have to deal with allocators (though more annoying on the code-wise) is to introduce a wrapper for int for which value-initialization does not do anything: 一种不同的方法,在你不必处理分配器的意义上更简单(虽然在代码方面更烦人)是为int引入一个包装器,值初始化不会做任何事情:

template <class T>
struct Wrapper {
    Wrapper() { }
    T value;
};

std::vector<Wrapper<int>> v(100);              // not zero-initialized
for (int i = 0; i < 100; i++) v[i].value = i;  // but have to do this... 

Note that simply using reserve() and push_back() is insufficient - that's still quite a bit more work that needs to be done than simply assigning by index after default-initialization, and if you're latency sensitive enough to have asked this question, that can be significant. 注意,简单地使用reserve()push_back()是不够的 - 除了在默认初始化之后简单地通过索引分配之外,还需要做更多的工作,并且如果你对延迟敏感到足以提出这个问题,这可能很重要。

Reading the link from the question, it seems you'd be happy using a vector if it didn't call an unnecessary constructor for every element. 从问题中读取链接,如果它没有为每个元素调用不必要的构造函数,那么使用vector似乎很高兴。 There are techniques to eliminate this overhead. 有一些技术可以消除这种开销。

std::vector<int> v;
v.reserve(100);
for (int i = 0; i < 100; i++) v.emplace_back(rand());
std::sort(v.begin(), v.end());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM