从函数返回 STL 向量 - 复制成本

2024-04-22

当您从函数返回 stl 向量时:

vector<int> getLargeArray() {  ...  }

返回将是一个昂贵的复制操作吗?我记得在某处读到向量分配很快——我是否应该要求调用者传递引用?

void getLargeArray( vector<int>& vec ) {  ...  }

假设你的函数构造并返回新数据,你应该按值返回,并尝试确保函数本身有一个返回点,该返回点返回一种类型的变量vector<int>,或者最坏的情况是几个返回点都返回相同的变量。

这确保您将在任何可靠的编译器上获得指定的返回值优化,从而消除one潜在副本(从函数中的值到返回值的副本)。还有其他方法可以实现返回值优化,但它并不完全可预测,因此简单的规则是安全的。

接下来,您希望消除从返回值到调用者对其执行的任何操作的潜在副本。这是调用者要解决的问题,而不是被调用者的问题,基本上有三种方法可以做到这一点:

  • 使用对函数的调用作为初始化程序vector<int>,在这种情况下,任何可靠的 C++ 编译器都会删除该副本。
  • 使用 C++11,其中vector具有移动语义。
  • 在 C++03 中,使用“交换优化”。

也就是说,在C++03中don't write

vector<int> v;
// use v for some stuff
// ...
// now I want fresh data in v:
v = getLargeArray();

Instead:

getLargeArray().swap(v);

这避免了所需的复制分配(不得省略[*])v = getLargeArray()。在 C++11 中不需要它,其中有一个便宜的移动分配而不是昂贵的复制分配,但当然它仍然有效。

另一件需要考虑的事情是你是否真的想要vector作为界面的一部分。您可以改为编写一个函数模板,该模板采用输出迭代器,并将数据写入该输出迭代器。想要向量中的数据的调用者可以传入以下结果std::back_inserter,因此想要数据的调用者也可以deque or list。提前知道数据大小的调用者甚至可以只传递一个向量迭代器(适当地resize()d 首先)或指向足够大数组的原始指针,以避免开销back_insert_iterator。有一些非模板方法可以做同样的事情,但它们很可能会以某种方式产生调用开销。如果您担心复制的成本int每个元素,那么您就会担心每个元素的函数调用的成本。

如果您的函数不构造并返回新数据,而是返回某些现有数据的当前内容vector<int>并且不允许更改原件,那么当您按值返回时,您将无法避免至少一份副本。因此,如果其性能已被证实存在问题,那么您需要查看除按值返回之外的其他 API。例如,您可以提供一对可用于遍历内部数据的迭代器、一个通过索引在向量中查找值的函数,甚至(如果性能问题严重到需要暴露您的内部),对向量的引用。显然,在所有这些情况下,您都会更改函数的含义 - 现在不再为调用者提供“他们自己的数据”,而是提供其他人的数据的视图,这些数据可能会发生变化。

[*] 当然,“好像”规则仍然适用,并且人们可以想象一种 C++ 实现,它足够聪明,能够意识到这一点,因为这是一个普通可复制类型的向量 (int),并且由于您没有获取任何指向任何元素的指针(我假设),因此它可以进行交换,并且结果“就像”它复制了一样。但我不会指望它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从函数返回 STL 向量 - 复制成本 的相关文章

随机推荐

  • MySQL:从另一台服务器选择

    恐怕我已经知道问题的答案 但我还是会问 当有两台 MySQL 数据库服务器时 我可以访问另一台服务器上存储的数据吗 换句话说 我能以某种方式这样做吗 INSERT INTO table x y z SELECT x y x y FROM o
  • Angular - mat-grid-list 不显示 传递的子项

    我正在使用角度材料设计组件 并想要创建一个自定义网格列表组件 该组件将根据其大小调整网格列表列的数量 组件模板如下所示
  • 让请求在curl中工作,但在Python中不起作用

    我正在尝试使用curl 制作一个 put 方法 一切正常 并且我得到了JSON curl X PUT d foo more foo http ip 6001 whatever api key whatever 但是在使用python时由于某
  • C 联合类型双关数组

    鉴于以下代码 我有一些与类型双关相关的问题 我看不出这没有违反严格的别名规则 但我无法指出具体的违规行为 我最好的猜测是 将联合成员传递到函数中违反了严格的别名 以下代码已开启编译器资源管理器 https godbolt org z bnY
  • 如何删除 ASP.Net MVC 中的 Home?

    我知道这个网站是使用 ASP Net MVC 编写的 但我在 url 中没有看到 Home 这向我证明这是可以做到的 我需要什么特殊路线 只需将 Home 更改为空字符串即可 routes MapRoute Home new action
  • Android 中可能存在哪些安全问题[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 为了了解 Android 设备上应如何保护强大的数据 我想了解哪些攻击是可能的 我开始写下我的知识 希望我能得到纠正 哪里错了或者哪里
  • “Uint8Array”类型的参数不可分配给“number[]”类型的参数

    基于crypto subtle exportKey spki cryptoKey https developer mozilla org en US docs Web API SubtleCrypto exportKey我想转换返回的Arr
  • 什么环境变量控制dyld?

    有许多环境变量控制 dyld 启动 其中一些对于调试性能问题非常有用 并非所有这些都被记录下来 这些在 dyld 手册页中有解释 至少在 macOS 10 13 上 DYLD FRAMEWORK PATH DYLD FALLBACK FRA
  • 如何从外部向azure Devops构建管道传递参数来控制任务执行?

    我的查询是 如何将参数传递给外部的azure Dev ops构建管道来控制任务执行 详细解释如下 我在 azure Dev ops 中有一个项目 它有一个构建管道 配置了一系列任务 涉及构建解决方案 生成可部署包等 通常 这会执行得很好 没
  • 在 Clang AST 中查找声明的父级

    我正在使用 clang 进行一些分析 我需要在 AST 中找到声明的父级 例如 在下面的代码中我有int x我想获取它的父级 它应该是函数声明 int main int x return 0 我知道正如这个链接中提到的http commen
  • AWS推送通知服务集成错误

    我正在尝试将亚马逊推送通知集成到我的 iPhone 应用程序中 我确实正确地遵循了此处提供的教程 我在创建平台端点时收到此错误 似乎是身份池的权限问题 CognitoIdentityCredentials is not authorized
  • 组合学:构建 10 组,每组 100 个元素,同时元素保持排序

    我有一个关于组合学的问题 不幸的是 我无法抽象地描述它 所以我尝试用一 个故事来解释它 Problem 校园里有 100 个孩子 它们都有独特的高度 假设值为 100 199 厘米 您想要建立 10 个小组 每个小组由 1 99 名儿童组成
  • boost::filesystem::unique_path() 如何解决 C++ 中 mkstemp 类似物的需求?

    An old 功能要求 https svn boost org trac boost ticket 590对于 Boost 来说 请求的功能类似于mkstemp http pubs opengroup org onlinepubs 0096
  • SyntaxError:属性列表后缺少 } [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions Firef
  • 在 Flex 中的 Spark TextInput 内添加搜索图标

    我想在 Spark TextInput 控件内添加搜索图标 有没有一种方法可以扩展 TextInput 控件并向其添加一个子控件 Thanks 你不应该延长TextInput本身 Spark 架构的主要功能是剥皮的可能性 您可以根据标准创建
  • Java 8流-如何从子实体中查找父实体?

    我有一个类似的场景 public class A private String id ManyToMany private Set b bSet getters and setters and public class B private
  • 为什么 JavaScript 文件在我的 Cake 插件中被解析为 PHP?

    我正在开发的 Cake 插件中包含的 JavaScript 之一出现问题 由于某种原因 JavaScript 文件被解析为 PHP 文件 因此加载该文件会抛出此错误 这是 PHP 解析错误 b Parse error b syntax er
  • 将 Python Pandas 数据帧上传到 MySQL - 内部错误:1366,“字符串值不正确”

    我正在尝试将 Pandas 数据帧写入 MySQL 数据库 并使用了以下代码 engine sqlalchemy create engine mysql pymysql root password localhost skills char
  • 设置 $_POST 变量

    我有一个使用 POST 的表单和一个变量 如何在 POST 中设置该变量 以便在提交表单后 我仍然可以获得该变量 我刚刚尝试过 POST variable variable 最终变成空的 您应该将该变量作为隐藏字段放入表单中 或者使用会话变
  • 从函数返回 STL 向量 - 复制成本

    当您从函数返回 stl 向量时 vector