简体   繁体   English

C ++中的返回向量标准

[英]Returning Vectors standard in C++

Now, I know this is a common question, but I haven't been able to really find a straight answer on this. 现在,我知道这是一个常见问题,但是我还没有真正找到一个直接的答案。 This is really a question about standards. 这确实是关于标准的问题。 I am working on a project involving the genetic algorithm. 我正在从事一个涉及遗传算法的项目。 But I'm running into a bottleneck when it comes to returning a vector. 但是,在返回向量时,我遇到了瓶颈。 Is there a "proper" way to do this. 有没有一种“适当的”方法来做到这一点。 Normally I use dynamically allocated arrays, and return a pointer to a newly created array. 通常,我使用动态分配的数组,并返回一个指向新创建的数组的指针。

obj* func(obj* foo);

That way, everything is efficient and there is no copying of data. 这样,一切都是高效的,并且没有数据复制。 Is there an equivalent to doing this with a vector? 是否有等同于使用向量执行此操作的方法? This vector has objects in it, so returning it by value would be slow I imagine. 此向量中包含对象,因此我想按值返回它会很慢。 Is the only solution to pass a "resultant" vector by reference? 是唯一通过引用传递“结果”向量的解决方案吗?

void func(vector<obj> &input, vector<obj> &result);

And, on a side note for future reference, is it standard practice to use a vector or other STL container over a dynamically allocated array? 而且,作为将来的参考,在动态分配的数组上使用向量或其他STL容器是否是标准做法? Are dynamically allocated arrays only used as a low level tool for designing containers? 动态分配的数组是否仅用作设计容器的底层工具? Are they just a relic of the past? 他们只是过去的遗物吗?

vector<obj> func(const vector<obj>& input);

All compilers implement RVO either by default or when you turn optimizations on, if you don't turn optimizations on you don't care about performance, so that would not be an issue anyway. 默认情况下,或者在您打开优化功能时,所有编译器都将实现RVO,如果您不打开优化功能,您就不会在意性能,因此无论如何这都不是问题。

If your compiler is C++11 conforming, then in the worst case instead of copying 1 pointer you will pay for 3 pointers when move semantics kick in, which compared with the cost of allocating the memory is really no cost. 如果您的编译器符合C ++ 11,那么在最坏的情况下,移动语义开始时,您无需支付1个指针,而是支付3个指针,这与分配内存的开销相比实际上是没有代价的。

Build a simple meaningfull interface, then measure the performance and bottlenecks and optimize from there. 构建一个简单的有意义的界面, 然后评估性能和瓶颈并从那里进行优化。

Depending on your use pattern, if you can reuse the output container, you might want to transform the above into: 根据您的使用模式,如果可以重复使用输出容器,则可能需要将以上内容转换为:

void func(vector<obj>& output, const vector<obj>& input);

This will have the same performance when creating a new vector, but if you call this function in a loop, you may be able to avoid a few allocations: 创建新向量时,它具有相同的性能,但是如果您在循环中调用此函数,则可以避免一些分配:

std::vector<obj> output;
for ( ... ) {
   output.clear();
   func(output, input);

// compare with
for ( ... ) {
   std::vector<obj> output = func(input);

In the first block of code, if all of the vectors are of the same size, the clear() will remove the elements but leave the buffer intact, so that the next call to func need not allocate. 在第一个代码块中,如果所有向量的大小都相同,则clear()将删除元素,但保留缓冲区不变,因此对func的下一次调用无需分配。 In the second case it needs to allocate inside func and will deallocate at the end of the scope. 在第二种情况下,它需要在func内部分配,并将在范围的末尾取消分配。

This is a slightly uglier interface to use, so I would opt for the first one (which semantically is cleaner), and use the second only if the first proves to have an issue with multiple allocations. 这是一个使用起来比较难看的接口,因此我会选择第一个接口(从语义上讲更干净),并且仅当第一个接口证明存在多个分配问题时才使用第二个接口。

Is the only solution to pass a "resultant" vector by reference? 是唯一通过引用传递“结果”向量的解决方案吗?

No. You can also pass an iterator, like algorithms do: 不。您还可以传递迭代器,就像算法一样:

void func( InputIt first, InputIt last, OutputIt res);

you can then make this a template: 然后可以将其作为模板:

template< class InputIt, class OutputIt >
void func( InputIt first, InputIt last, OutputIt res);

If you want to be reasonably sure that your function doesn't copy the vector, then: 如果要合理确定函数不会复制矢量,则:

 void func(const vector<obj> &input, vector<obj> &result);

If you are OK with relying on compiler "return value optimisation" (RTVO) (most good compilers do this): 如果您可以依靠编译器“返回值优化”(RTVO)(大多数优秀的编译器都可以这样做):

 vector<obj> func(const vector<obj> &input); 

Return value optimisation is essentially where the compiler knows that we're returning a copy of a vector, so it removes the "extra copy" that would normally be needed in returning the content of, in this case, vector<obj> from func . 从本质上说,返回值优化是编译器知道我们要返回向量的副本的地方,因此它删除了通常从func返回vector<obj>的内容所需的“额外副本”。 A C++11 compliant compiler should use the "move constructor" if it is not able to do RTVO, which is also small cost in the whole scheme of things. 如果C ++ 11兼容的编译器不能执行RTVO,则应使用“移动构造函数”,这在整个方案中也很小。

If you are happy to dynamically allocate the vector itself, you can return a pointer to it, but this is a poor solution: 如果您愿意动态分配向量本身,则可以返回指向它的指针,但这是一个较差的解决方案:

vector<obj>* func(const vector<obj> &input);

This solution relies on allocating vector<obj> , which means that something somewhere has to delete the result of the call to func . 此解决方案依赖于分配vector<obj> ,这意味着某些地方必须deletefunc的调用结果。 Maintenance of such code, if func is called many times, gets rather nasty (especially if func gets called lots of times, which may well be the case in a genetics analysis situation). 如果多次调用func ,则此类代码的维护会变得非常麻烦(尤其是多次调用func时,在遗传学分析情况下可能就是这种情况)。

It is usually hard to achieve a return of a reference, so you are probably doing something wrong if you do - DO NOT DO THIS (unless you know what you are doing and why): 通常很难获得引用的返回,因此,如果您这样做可能会做错了-请勿这样做(除非您知道自己在做什么以及为什么):

vector<obj>& func(const vector<obj> &input); 

Of course, it REALLY depends on what you are doing with the vectors, and there may be other solutions that are even better, if you give a more concrete example of what you are doing inside the function. 当然,这实际上取决于您对向量的处理方式,如果您给出函数内部处理方式的更具体示例,则可能还有其他更好的解决方案。

By the way: 顺便说说:

obj *func(obj *input)

is a maintenance nightmare, because if obj* is allocated in func , it is now for the caller to maintain this structure. 这是维护方面的噩梦,因为如果在func分配了obj* ,则现在调用方可以维护此结构。

Finally, ALWAYS when you deal with performance, it's important to benchmark with YOUR compiler, on YOUR machine(s). 最后,总是要处理性能时,在您的计算机上使用您的编译器进行基准测试很重要。 Different compilers and different systems behave differently - guessing based on looking at the source-code is a very poor solution for understanding what code will be generated and how fast it is. 不同的编译器和不同的系统会有不同的行为-基于查看源代码的猜测对于理解将生成什么代码及其速度有多不好。

If you can, always use a reference (&) instead of using the class itself. 如果可以,请始终使用引用(&),而不要使用类本身。 This even refers to smart pointers (std::shared_ptr), because you will avoid an extra copy even of the pointer itself. 这甚至涉及智能指针(std :: shared_ptr),因为您甚至可以避免指针本身的额外复制。 And just to make sure that your returned pointer does not get overwritten, pre-pend const to it, so: 只是为了确保您返回的指针不会被覆盖,可以在其前面加上const,因此:

void Function(const std::shared_ptr<SomeClass> &someObject);

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

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