关于传递参数在C++中如何工作的问题

Questions on how passing arguments works in C++

本文关键字:工作 问题 何工作 参数 于传递 C++      更新时间:2023-10-16

所以我是一个经验丰富的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类一无所知,哪种方法是首选方法?

传递参数的首选方式是
void fn(const vector<Object> &vec);
当然前提是你不修改它。在c++中使用指针,比如情况2和3,通常不是一个好的做法
现在版本1:
void fn(vector<Object> vec);
通常会被认为是糟糕的,因为它是一个副本,但有时它是必要的。请记住,有时编译器能够在临时情况下使用副本省略来优化副本,如果副本没有被修改(但在这种情况下应该使用const-ref),

您所说的一切都是正确的。

如果无论如何都要在函数中复制矢量,或者如果要在fn中修改vec,但不修改原始副本,请使用#1。然后你可以把副本保存在里面,让编译器(可能)为你做副本。

如果要修改原始矢量(来自fn外部),请使用#4。

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

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

不要使用#2,因为将指针放入向量会非常困难。存储器将需要是new d和delete d,并且它将容易出错。[强制共享ptr注释]。

您的#3不是惯用的C++。这很好,但在这种情况下,惯用的C++会避开指针而使用引用。

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

一般来说,拥有指针向量是不受欢迎的。当矢量超出范围时,这些指针将不会自动删除。你必须确保自己删除它们。如果您的代码在此之前的任何时候抛出异常,那么您是否仍会发生内存泄漏。

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

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

1) 如果你有

std::vector<Object> v;

那么,很明显,您不能为过载void fn(vector<Object*> vec);调用fn(v)

2) 你说:

"我对向量类中包含的内容了解不够"。。。

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