4

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

4

4 回答 4

3

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

于 2013-08-06T17:27:05.107 回答
1

这都是正确的。方法 2 确实会复制 vec,因为它的元素是指向它的指针,Object所以它只会复制那些指针,而不是实际的对象。这与将指针数组传递给Object.

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

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

于 2013-08-06T17:26:58.737 回答
1

你说的一切都是正确的。

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

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

如果您根本不想修改向量,请使用 #4 和 a const

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

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

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

于 2013-08-06T17:32:04.710 回答
0

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

1)如果你有

std::vector<Object> v;

那么,显然,您不能要求fn(v)重载void fn(vector<Object*> vec);

2) 你说:

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

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

于 2013-08-06T17:40:15.480 回答