为什么当用于初始化另一个对象时,参数是否通过值传递? [英] Why should arguments be passed by value when used to initialize another object?

查看:129
本文介绍了为什么当用于初始化另一个对象时,参数是否通过值传递?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将对象传递给函数时,可以选择通过值或 const& 传递参数。特别是当对象创建可能是昂贵的,并且它是内部突变或用于初始化另一个对象时,建议是按值传递对象。例如:

When passing objects to functions there is the choice to pass arguments either by value or by const&. Especially when the object is possibly expensive to create and it is internally mutated or used to initialize another object the recommendation is to pass the object by value. For example:

class Foo {
    std::vector<std::string> d_strings;
public:
    Foo(std::vector<std::string> strings): d_strings(std::move(strings)) {}
    // ...
};

传统的方法是声明 strings 参数 std :: vector< std :: string> const& 并复制参数。上面的构造函数的值参数也需要复制!

The conventional approach would be to declare the strings parameter as std::vector<std::string> const& and copy the argument. The value argument to the constructor above also needs to be copied!

为什么优先传递值而不是传递 const& code>? c> $

Why is it preferable to pass by value rather than pass by const&?

推荐答案

const& 有一个保证副本:没有其他方法来保持一个,好,副本的参数,而不是复制它。

When passing the strings argument by const& there is a guaranteed copy: there is no other way to get hold a, well, copy of the argument other than copying it. The question becomes: how is that different when passing by value?

当参数通过值 strings 时,对象清楚地在其他地方使用,其内容可以移动。将扩展的移动构建到复制对象可能仍然相对便宜。例如,在 std :: vector< std :: string> 的情况下,移动只是将一些指针复制到新对象并设置几个指针来指示到原始对象,它不应该释放任何东西。

When the argument is passed by value the strings object is clearly used nowhere else and its content can be moved. Move construction of expansive to copy objects may still be comparatively cheap. For example, in the case of the std::vector<std::string> the move is just copying a few pointers to the new object and setting a few pointers to indicate to the original object that it shouldn't release anything.

但仍然需要创建参数。然而,可以省略参数的创建而不创建新对象。例如

There is still the need to create the argument, though. However, the creation of the argument may be elided without creating a new object. For example

Foo f(std::vector<std::string>{ "one", "two", "three" });

将创建一个具有三个字符串的向量,并构造 Foo 构造很可能被省略。在最坏的情况下,参数是通过移动临时向量来构造的,避免了副本。

will create a vector with three strings and construction of the argument to the Foo construct is most likely elided. In the worst case, the argument is constructed by moving the temporary vector, avoiding a copy, too.

当然,还有一个副本需要创建。例如,在

There are, of course, cases where a copy still needs to be created. For example, in the case

std::vector<std::string> v{ "one", "two", "three" };
Foo                      f(v);

参数由副本创建。然后将准备好的副本移动到成员。在这种情况下,传递 const& 会更好,因为只需要一个副本构造,而不是一个副本构造(创建参数)

The argument is created by a copy. The ready made copy is then moved to the member. In this case pass by const& would have been better because only a copy construction would have been needed rather than a copy construction (to create the argument) followed by a move construction (to create the member) being done.

也就是说,传递值可以完全隐藏副本,只需移动一个副本。在最坏的情况下,当需要复制参数时,需要执行附加的移动。由于移动通常被假定为一个廉价的操作,所以期望的是,对于需要被传输的对象的总价值传递导致更好的性能。

That is, passing by value enables possibly eliding a copy entirely and just having a move. In the worst case, when the argument needs to be copied anyway, an additional move needs to be performed. Since the move is generally assumed to be a cheap operation the expectation is that overall pass by value for objects which need to be transferred results in better performance.

这篇关于为什么当用于初始化另一个对象时,参数是否通过值传递?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆