优化向量赋值 c++

Posted

技术标签:

【中文标题】优化向量赋值 c++【英文标题】:Optimizing vector assignment c++ 【发布时间】:2016-01-30 22:16:03 【问题描述】:

我有一个返回向量的函数。让我们将其命名为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();
    ...

【问题讨论】:

【参考方案1】:

优化赋值的最好方法是根本不赋值,而是使用初始化

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

几乎可以肯定,编译器会直接将v创建成v2,无需任何复制。

【讨论】:

使用move构造函数 我在创建帖子之前尝试过。效果不好。 试试 std::vector v2 = std::move(merge(...)); @Vincent merge(....) 已经是一个右值,所以这实际上是一种悲观 @ValeryBaturin 这是正确的答案,如果您仍然遇到问题,那么还有另一个您没有显示代码的错误。如果您发布一个显示问题的实际程序,而不是一堆点,那就更好了。 See here for guidelines.【参考方案2】:

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

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();
    ...

【讨论】:

我不喜欢这个,因为你总是需要在使用函数之前创建向量。但无论如何,这是一个解决方案。谢谢! 我很好,但我希望你明白这是返回集合时的事实上的标准。在某些情况下,接受的答案仍会创建一个副本,通常最好设计您的代码以涵盖各种场景。例如,请记住,在 C 中您甚至不能返回数组。此外,如果您仍然创建它,那么之前创建它有什么问题?编码愉快! @AndréFratelli:在设置它的值之前创建它的两个最大问题 a) 你不能声明它 const ; b) 风格很差。如果调用者重用变量而忘记清除它,这也是一个潜在的问题。 @MartinBonner 我同意你不能将它声明为 const,但是你可以制作一个 const 副本。考虑到风格很差,那就是你大错特错的地方。就像我说的,在返回集合时,这是编程中事实上的 标准,您会在文献中找到很多。你不喜欢它的事实是无关紧要的,因为它确实是这个问题通常是如何解决的,即使移动构造函数可用。见this讨论 这不是事实上的标准;这是选择之一——通常是一个糟糕的选择。该讨论是关于它确实具有 一些 优势(通过返回类型重载)的情况之一 - 但正确的解决方案将有不同的函数名称(尽管在模板化代码中可能会出现问题)。 【参考方案3】:

您可以将您的向量临时绑定到参考:

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

auto&& x = f();
std::sort(x.begin(), x.end());  // example

【讨论】:

‘function’既有‘extern’又有初始化器extern std::vector function(...);【参考方案4】:

您有多种选择:

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

    开启优化(您会惊讶于该步骤解决了多少关于 SO 的“优化”问题)。

    升级到 C++11 编译器。编译器应该对向量使用移动赋值运算符,这是非常有效的(任何体面的库都会将内部分配的数组从临时转移到目标,无需内存分配和元素复制)。

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

    如果您已经测量,而这仍然是性能瓶颈,并且您无法让编译器实现 RVO,那么您别无选择,只能传递向量根据 André Fratelli 在his answer

    中的建议

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

从函数结果初始化 函数结果赋值 传入要填充的向量。

【讨论】:

我可以使用 c++11,但没有让程序变慢的选项。我有时间限制的比赛等等。谢谢您的回答。 RVO 很酷,我听说过。

以上是关于优化向量赋值 c++的主要内容,如果未能解决你的问题,请参考以下文章

将单行向量(数组)赋值转换为经典数组,C++ 转换为 C

为指针向量赋值

C++ 向量操作优化

向量上的 C++ operator() 优化

关于c++指针赋值的问题

在 C++ 中通过网格/矩阵找到成本优化路径