C++ 优化向量赋值c++;

C++ 优化向量赋值c++;,c++,algorithm,vector,C++,Algorithm,Vector,我有一个返回向量的函数。让我们把它命名为v。我在函数中使用v.begin()和v.end()。如何使用.begin()和.end()而不创建新的向量v2来存储以前的向量v,以便访问方法 我的意思是: std::vector<int> merge(...) { ... return v; } void mergeSort(...) { ... std::vector<int> v2; v2 = merge(...); I_ne

我有一个返回向量的函数。让我们把它命名为
v
。我在函数中使用
v.begin()
v.end()
。如何使用
.begin()
.end()
而不创建新的向量
v2
来存储以前的向量
v
,以便访问方法

我的意思是:

std::vector<int> merge(...) {
    ...
    return v;
}
void mergeSort(...) {
    ...
    std::vector<int> v2;
    v2 = merge(...);
    I_need_this = v2.begin();
    And_I_really_need_this_too = v2.end();
    ...
}
std::向量合并(…){
...
返回v;
}
无效合并排序(…){
...
std::向量v2;
v2=合并(…);
我需要这个=v2.begin();
而且我真的需要这个=v2.end();
...
}

当您需要返回集合时,为了防止它们被复制,一种常见的模式是通过非常量引用传递集合并对原始集合进行更改。这意味着调用方负责实例化集合,而不是被调用方,因此不会发生复制。下面是一个例子:

void merge(std::vector<int> & result, ...) {

    // Do changes to result
    ...
}
void mergeSort(...) {
    ...
    std::vector<int> v;
    merge(v, ...);

    // This is OK now
    I_need_this = v.begin();
    And_I_really_need_this_too = v.end();
    ...
}
void合并(标准::向量和结果,…){
//对结果进行更改
...
}
无效合并排序(…){
...
std::向量v;
合并(v,…);
//现在可以了
我需要这个;
而且我真的需要这个;
...
}

您可以将向量临时绑定到引用:

extern std::vector<int> f();

auto&& x = f();
std::sort(x.begin(), x.end());  // example
extern std::vector f();
自动&x=f();
排序(x.begin(),x.end());//例子

优化分配的最佳方法是根本不分配,而是使用初始化

std::vector<int> v2 = merge(...);
std::vector v2=merge(…);

几乎可以肯定,编译器将直接在
v2
中创建
v
,而不进行任何复制。

您有许多选项:

  • 别担心。性能通常并不那么重要

  • 打开优化(你会惊讶于有多少“优化”问题是通过这一步解决的)

  • 升级到C++11编译器。编译器应该使用vector的move赋值操作符,这是非常有效的(任何合适的库都会将内部分配的数组从临时数组传输到目标数组,而无需内存分配和元素复制)

  • 如果您不能使用C++11编译器,或者您已经测量过了,并且这仍然是一个性能瓶颈,请按照Bo Person在中的建议切换到初始化

  • 如果您已经进行了测量,但这仍然是一个性能瓶颈,并且您无法让编译器实现RVO,那么您别无选择,只能按照AndréFratelli在年提出的建议,按值传递向量

  • 如果我们不再讨论优化问题,而是讨论编写好的、清晰的代码,那么我会按照优先顺序推荐:

    extern std::vector<int> f();
    
    auto&& x = f();
    std::sort(x.begin(), x.end());  // example
    
    • 从函数结果初始化
    • 函数结果赋值
    • 传入要填充的向量

    通过使用
    move
    constructor,我在创建post之前进行了尝试。它工作不好。请尝试std::vector v2=std::move(merge(…)@Vincent
    merge(…)
    已经是一个右值,所以实际上是一个右值pessimization@ValeryBaturin这是正确的答案,如果您仍然有问题,那么还有一个错误您没有显示代码。如果你发布一个显示问题的实际程序,而不是一堆点,那会好得多函数“”同时具有“extern”和初始值设定项extern std::vector函数(…);我不喜欢这个,因为在使用函数之前,您总是需要创建向量。但无论如何,这是一个解决办法。非常感谢。我很好,但我希望你明白,这是归还收藏品的事实标准。在某些情况下,被接受的答案仍然会创建一个副本,通常设计代码以涵盖各种场景是一个好主意。例如,请记住,在C中甚至不能返回数组。此外,如果你要创建它,那么之前创建它有什么问题?快乐编码@AndréFratelli:在设置它的值之前创建它有两个最大的问题a)你不能声明它
    const
    ;b) 这是非常糟糕的风格。如果调用者重复使用变量而忘记清除它,这也是一个潜在的问题。@MartinBonner我同意你不能声明它为常量,但是你可以创建一个常量副本。考虑到你的风格很差,你就错了。正如我所说,这是编程中返回集合的事实标准,你会在文献中发现很多。您不喜欢它这一事实是无关紧要的,因为这确实是这个问题通常是如何解决的,即使在移动构造函数可用的情况下也是如此。参见讨论它不是事实上的标准;这是一个选择——通常是一个糟糕的选择。这个讨论是关于它确实有一些优点(按返回类型重载)的情况之一,但是正确的解决方案会有不同的函数名(尽管这在模板化代码中可能会有问题)。我可以使用c++11,但没有使程序变慢的选项。我参加了一场有时间限制的比赛。谢谢你的回答。RVO很酷,我听说了。