c++ 为什么通过常量引用而不是通过值传递?

puruo6ea  于 12个月前  发布在  其他
关注(0)|答案(8)|浏览(102)

据我所知:当你通过值传递时,函数会创建一个传递参数的本地副本并使用它;当函数结束时,它就超出了作用域。当你通过const引用传递时,函数使用了一个对传递的参数的引用,这个参数不能被修改。我不明白,然而,为什么一个人会选择一个而不是另一个,除非在一个参数需要被修改和返回的情况下。如果你有一个没有返回任何东西的void函数,为什么要选择一个而不是另一个呢?
编辑:所以基本上通过const引用传递避免了复制对象。那么在什么情况下复制对象是好的?我的意思是,如果一直优化性能,为什么不一直使用const引用呢?

cs7cruho

cs7cruho1#

有两个主要的考虑因素,一个是复制传递的对象的开销,第二个是当对象是局部对象时编译器可以做出的假设。
例如,在第一种形式中,在f的主体中,不能假设ab不引用同一个对象;所以a的值必须在对b的任何写入之后重新读取,以防万一。在第二种形式中,a不能通过对b的写入来改变,因为它是函数的本地值,所以这些重读是不必要的

void f(const Obj& a, Obj& b)
{
    // a and b could reference the same object
}

void f(Obj a, Obj& b)
{
    // a is local, b cannot be a reference to a
}

字符串
例如:在第一个例子中,编译器可以假设本地对象的值在进行无关调用时不会改变。如果没有关于h的信息,编译器可能不知道该函数引用的对象是否例如,该对象可能是由h修改的全局状态的一部分。

void g(const Obj& a)
{
    // ...
    h(); // the value of a might change
    // ...
}

void g(Obj a)
{
    // ...
    h(); // the value of a is unlikely to change
    // ...
}


不幸的是,这个例子并不是铁板一块。可以编写一个类,比如说,在其构造函数中向全局状态对象添加一个指向自身的指针,这样即使是类类型为 * 的局部对象也可能 * 被全局函数调用改变。尽管如此,仍然有可能为局部对象进行有效的优化,因为它们不能直接通过传入的引用进行别名,或者其他已经存在的物体。
在实际需要引用语义的情况下,应该选择通过const引用传递参数,或者只有在复制参数的开销超过潜在别名的代价时,才选择通过const引用传递参数。

szqfcxe2

szqfcxe22#

通过值传递参数并复制它们可能是昂贵的- const引用避免了昂贵的步骤,同时仍然向调用者保证对象不会被更改。
通常基本类型(intdouble,...)通过值传递,而类类型通过常量引用传递。
然而,在exceptions中,类类型的按值传递可能是有益的。

wgx48brx

wgx48brx3#

在某些情况下,复制一个对象可能会极大地影响性能。考虑一个参数为std::vector<long>的函数,你想传递100万个元素的vector。在这种情况下,你想使用const引用而不是通过值传递。在这个SO问题中,你可以找到简单的一般规则。

uhry853o

uhry853o4#

通过值传递参数的开销是将对象的副本传递给函数。
也许一个对象是不可复制的,你的选择是有限的。

lyr7nygr

lyr7nygr5#

有时候,复制一个对象可能会很昂贵,所以通过常量引用传递可以避免复制。否则,我会说,如果语义上需要的话,你应该简单地通过值传递。

cwdobuhd

cwdobuhd6#

为了避免制作不必要的副本,从而提高性能。

wrrgggsh

wrrgggsh7#

因为您将获得性能方面的好处。(以字节为单位)。现在,如果你通过值传递这个对象给一个函数,那么需要创建一个不必要的副本,但是你可以通过传递一个常量引用到这个对象本身而不创建副本来获得同样的效果。由于引用通常被存储为一个指针,传递引用的成本仅为sizeof(pointer)

gt0wga4j

gt0wga4j8#

数组不能通过值传递,所以这是使用常量指针的好时机。

相关问题