【问题标题】:Questions on how passing arguments works in C++关于传递参数如何在 C++ 中工作的问题
【发布时间】:2013-08-07 20:08:34
【问题描述】:

所以我是一个相当有经验的 C 程序员,经常使用 C++ 编程。这门语言有一些我从来没有自信过的微妙之处。例如,传递参数的最佳方法。

例如,假设我有一个名为 Object 的黑盒类(据我们所知,它可能有很多成员变量)和一个函数 fn,它以 Object 实例的向量作为其参数。在我看来,有四种基本的传递方式:

void fn(vector<Object> vec);
void fn(vector<Object*> vec);
void fn(vector<Object> *vec);
void fn(vector<Object> &vec);

当然,我们也可以对这些功能进行一些组合。

我想确认一下:

方法 1 将复制向量类,包括向量中每个 Object 实例的副本。这可能是一个巨大的过载,因此很糟糕。

(这个我不太确定)方法 2 将复制 vec 的所有方法变量,但它只会复制每个 Object 实例的地址。我对向量类中包含的内容知之甚少,无法知道这是否可取。

方法 3 和 4 相当简单,彼此相似,并且引入的开销最小。

这一切都正确吗?记住我们对 Object 类一无所知,哪种方法是首选方法?

【问题讨论】:

  • 首选方法取决于您要做什么,但如果您不想修改向量,也不想复制,则传递const 引用是通常的方法: void fn(const vecctor&lt;Object&gt;&amp; vec);.
  • How to pass parameters correctly? 的可能重复项 - 除了您的第二个选项没有被覆盖,因为它不完全相关

标签: c++ vector reference arguments


【解决方案1】:

传递参数的首选方式是
void fn(const vector&lt;Object&gt; &amp;vec);
当然前提是你不修改它。使用指针,如案例 2 和 3 在 C++ 中通常不是好的做法。
现在版本 1:
void fn(vector&lt;Object&gt; vec);
通常会被认为是不好的,因为它会复制但有时是必要的。请记住,有时编译器可以使用 copy elision 在临时的情况下优化副本,如果副本没有被修改(但在这种情况下你应该使用 const ref)

【讨论】:

  • 但是如果您需要在函数内部复制,版本 3 可能是首选,因为它允许复制省略的一些范围。
  • @juanchopanza 不是我说的,我以必要的方式结束了它
  • 差不多。它并不总是复制。
  • @juanchopanza 如果你修改它,它不会总是复制吗?
  • 我的意思是,如果你传递一个临时值,副本可以被省略。
【解决方案2】:

你说的都是对的。

如果您要在函数内复制向量,或者如果您想在fn 内修改vec,但不修改原始副本,则使用#1。然后您可以将副本保存在里面,让编译器(可能)为您完成副本。

如果你想修改原始向量(来自fn之外),那么使用#4。

如果您根本不想修改向量,请使用带有const 的#4:

void fn(const vector<Object> &vec);

不要使用#2,因为您将很难将指针放入向量中。内存必须是newd 和deleted,这样容易出错。 [强制性 shared_ptr 注释]。

您的#3 不是惯用的 C++。这很好,但在这种情况下,惯用的 C++ 避开了指针以支持引用。

【讨论】:

  • 如果函数要将向量的句柄存储到稍后(函数返回后)使用的某个地方,请使用#3。当需要处理生命周期问题时,惯用 C++ 使用指针(或智能指针)。
【解决方案3】:

这都是正确的。方法 2 确实会复制 vec,因为它的元素是指向 Object 的指针,所以它只会复制这些指针,而不是实际的对象。这与传递指向Object 的指针数组没有太大区别。

一般来说,指针向量是不被接受的。当向量超出范围时,这些指针不会被自动删除。您必须确保自己删除它们。如果您的代码在此之前的任何时候抛出异常,您仍然会出现内存泄漏。

如果对象很小,您应该使用对象向量,而不是指针。如果对象很大,则应使用智能指针向量。

【讨论】:

    【解决方案4】:

    基本上你做对了,其他人给出了很好的答案和评论。我只想添加两个cmets:

    1) 如果你有

    std::vector<Object> v;
    

    那么,很明显,你不能调用fn(v) 来处理过载void fn(vector&lt;Object*&gt; vec);

    2) 你说:

    “我对向量类中包含的内容知之甚少” ...

    std::vector 最流行的实现只有三个指针作为数据成员,复制这三个指针的成本非常小。但是,当您复制 std::vector 时,这不是发生的情况(如果它的复制构造函数是编译器生成的)。实际上std::vector 有一个复制构造函数,它(如你所说)复制原始std::vector 的所有元素。这还涉及内存分配,并且可能是一项非常昂贵的操作。

    【讨论】:

      猜你喜欢
      • 2011-02-09
      • 1970-01-01
      • 1970-01-01
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多