将整数作为常量引用传递给复制

时间:2021-08-09 16:55:59

This might be a stupid question, but I notice that in a good number of APIs, a lot of method signatures that take integer parameters that aren't intended to be modified look like:

这可能是一个愚蠢的问题,但我注意到,在很多api中,有很多方法签名采用不打算修改的整型参数:

void method(int x);

void方法(int x);

rather than:

而不是:

void method(const int &x);

无效的方法(const int x);

To me, it looks like both of these would function exactly the same. (EDIT: apparently not in some cases, see answer by R Samuel Klatchko) In the former, the value is copied and thus can't change the original. In the latter, a constant reference is passed, so the original can't be changed.

对我来说,它们的功能是一样的。(编辑:显然不是在某些情况下,见R Samuel Klatchko的回答),这个值是复制的,因此不能改变原来的值。在后者中,传递一个常量引用,因此不能更改原始引用。

What I want to know is why one over the other - is it because the performance is basically the same or even better with the former? e.g. passing a 16-bit value or 32-bit value rather than a 32-bit or 64-bit address? This was the only logical reason I could think of, I just want to know if this is correct, and if not, why and when you would prefer int x over const int &x and/or vice versa. Thanks.

我想知道的是,为什么一个人比另一个人表现得更好?例如,传递16位值或32位值而不是32位或64位地址?这是我能想到的唯一合乎逻辑的原因,我只是想知道这是否正确,如果不是,为什么和什么时候你更喜欢int x / const int &x,或者反之亦然。谢谢。

5 个解决方案

#1


42  

It's not just the cost of passing a pointer (that's essentially what a reference is), but also the de-referencing in the called method's body to retrieve the underlying value.

它不仅仅是传递一个指针的成本(这本质上就是引用),还包括在被调用方法的主体中去引用以检索底层值。

That's why passing an int by value will be virtually guaranteed to be faster (Also, the compiler can optimize and simply pass the int via processor registers, eliminating the need to push it onto the stack).

这就是为什么按值传递int将被保证更快(同时,编译器可以通过处理器寄存器优化并简单地传递int,从而无需将其推入堆栈)。

#2


33  

To me, it looks like both of these would function exactly the same.

对我来说,它们的功能是一样的。

It depends on exactly what the reference is to. Here is an admittedly made up example that would change based on whether you pass a reference or a value:

这完全取决于引用的是什么。这里有一个不可否认的例子,它会根据你是否通过引用或值来改变:

static int global_value = 0;

int doit(int x)
{
    ++global_value;
    return x + 1;
}

int main()
{
    return doit(global_value);
}

This code will behave differently depending on whether you have int doit(int) or int doit(const int &)

此代码的行为将根据您的int doit(int)或int doit(const int &)而有所不同

#3


2  

Integers are usually the size of the processor's native word and can pass easily into a registers. From this perspective, there is no difference between passing by value or passing by constant reference.

整数通常是处理器的本地字的大小,可以很容易地传递到寄存器中。从这个角度来看,传递值和传递常量引用没有区别。

When in doubt, print the assembly language listing for your functions to find out how the compiler is passing the argument. Print out for both pass by value and pass by constant reference.

当有疑问时,打印汇编语言清单,以了解编译器是如何传递参数的。通过值和常量引用进行输出。

Also, when passing by value, the function can modify the copy. When passing by constant reference, the function cannot modify the variable (it's marked as const).

此外,当传递值时,函数可以修改拷贝。当通过常量引用传递时,函数不能修改变量(它被标记为const)。

#4


1  

  • Depending on the underlying instruction set, an integer parameter can be passed as register or on the stack. Register is definitely faster than memory access, which would always be required in case of const refs (considering early cache-less architectures)

    根据底层的指令集,整数参数可以作为寄存器或堆栈传递。寄存器肯定比内存访问要快,在const refs(考虑到早期的无缓存体系结构)的情况下总是需要内存访问

  • You cannot pass an int literal as a const int&

    不能将整型文字传递为const int&

  • Explicit type-casts allow you cast a const int& into * (const int *) opening the possibility to change the value of the passed reference

    显式类型转换允许您将一个const int&into * (const int *)打开,从而改变传递的引用的值。

#5


0  

There will probably be a very, very small de-optimization for passing by reference, since at the very least one dereference will need to occur to get the actual value (unless the call is inlined, the compiler cannot simply pass the value due to the fact that the call site and function might be separately compiled, and it's valid and well-defined to cast away the const for a passed parameter that isn't actually const itself - see What are the benefits to passing integral types by const ref). Note, however, that the 'de-optimization' is likely to be so small as to be difficult to measure.

可能会有一个非常,非常小的de-optimization按引用传递,因为至少一个废弃需要发生的实际价值(除非内联调用,编译器不能简单地通过价值因为调用站点和函数可以单独编译,这是有效的和良好定义的抛弃的常量传递参数,并不是常量本身,看到有什么好处通过积分类型常量ref)。然而,请注意,“去优化”可能非常小,以至于很难度量。

Most people seem to dislike pass-by-const-ref for built-ins because of this (some very much). However, I think that it it might be preferable in some cases if you want the compiler to assist you in ensuring that the value isn't accidentally changed within the function. It's not a big thing, but sometimes it might help.

因为这个原因,大多数人似乎不喜欢“内建”(有些人非常讨厌)。但是,我认为在某些情况下,如果您希望编译器帮助您确保在函数中不意外地更改值,那么最好使用它。这不是什么大事,但有时它可能会有帮助。

#1


42  

It's not just the cost of passing a pointer (that's essentially what a reference is), but also the de-referencing in the called method's body to retrieve the underlying value.

它不仅仅是传递一个指针的成本(这本质上就是引用),还包括在被调用方法的主体中去引用以检索底层值。

That's why passing an int by value will be virtually guaranteed to be faster (Also, the compiler can optimize and simply pass the int via processor registers, eliminating the need to push it onto the stack).

这就是为什么按值传递int将被保证更快(同时,编译器可以通过处理器寄存器优化并简单地传递int,从而无需将其推入堆栈)。

#2


33  

To me, it looks like both of these would function exactly the same.

对我来说,它们的功能是一样的。

It depends on exactly what the reference is to. Here is an admittedly made up example that would change based on whether you pass a reference or a value:

这完全取决于引用的是什么。这里有一个不可否认的例子,它会根据你是否通过引用或值来改变:

static int global_value = 0;

int doit(int x)
{
    ++global_value;
    return x + 1;
}

int main()
{
    return doit(global_value);
}

This code will behave differently depending on whether you have int doit(int) or int doit(const int &)

此代码的行为将根据您的int doit(int)或int doit(const int &)而有所不同

#3


2  

Integers are usually the size of the processor's native word and can pass easily into a registers. From this perspective, there is no difference between passing by value or passing by constant reference.

整数通常是处理器的本地字的大小,可以很容易地传递到寄存器中。从这个角度来看,传递值和传递常量引用没有区别。

When in doubt, print the assembly language listing for your functions to find out how the compiler is passing the argument. Print out for both pass by value and pass by constant reference.

当有疑问时,打印汇编语言清单,以了解编译器是如何传递参数的。通过值和常量引用进行输出。

Also, when passing by value, the function can modify the copy. When passing by constant reference, the function cannot modify the variable (it's marked as const).

此外,当传递值时,函数可以修改拷贝。当通过常量引用传递时,函数不能修改变量(它被标记为const)。

#4


1  

  • Depending on the underlying instruction set, an integer parameter can be passed as register or on the stack. Register is definitely faster than memory access, which would always be required in case of const refs (considering early cache-less architectures)

    根据底层的指令集,整数参数可以作为寄存器或堆栈传递。寄存器肯定比内存访问要快,在const refs(考虑到早期的无缓存体系结构)的情况下总是需要内存访问

  • You cannot pass an int literal as a const int&

    不能将整型文字传递为const int&

  • Explicit type-casts allow you cast a const int& into * (const int *) opening the possibility to change the value of the passed reference

    显式类型转换允许您将一个const int&into * (const int *)打开,从而改变传递的引用的值。

#5


0  

There will probably be a very, very small de-optimization for passing by reference, since at the very least one dereference will need to occur to get the actual value (unless the call is inlined, the compiler cannot simply pass the value due to the fact that the call site and function might be separately compiled, and it's valid and well-defined to cast away the const for a passed parameter that isn't actually const itself - see What are the benefits to passing integral types by const ref). Note, however, that the 'de-optimization' is likely to be so small as to be difficult to measure.

可能会有一个非常,非常小的de-optimization按引用传递,因为至少一个废弃需要发生的实际价值(除非内联调用,编译器不能简单地通过价值因为调用站点和函数可以单独编译,这是有效的和良好定义的抛弃的常量传递参数,并不是常量本身,看到有什么好处通过积分类型常量ref)。然而,请注意,“去优化”可能非常小,以至于很难度量。

Most people seem to dislike pass-by-const-ref for built-ins because of this (some very much). However, I think that it it might be preferable in some cases if you want the compiler to assist you in ensuring that the value isn't accidentally changed within the function. It's not a big thing, but sometimes it might help.

因为这个原因,大多数人似乎不喜欢“内建”(有些人非常讨厌)。但是,我认为在某些情况下,如果您希望编译器帮助您确保在函数中不意外地更改值,那么最好使用它。这不是什么大事,但有时它可能会有帮助。