C++ 64 位 int:按引用传递或按值传递

发布于 2024-10-02 05:06:53 字数 253 浏览 1 评论 0原文

这是一个关于 64 位整数的效率问题。假设我不需要修改“int”参数的值,我应该通过值还是引用传递它。

假设 32 位机器:

1) 32 位 int:我猜答案是“按值传递”,因为“按引用传递”将产生额外的内存查找开销。

2)64位int:如果我通过引用传递,我只传递堆栈上的32位地址,但需要额外的内存查找。那么它们哪个更好(参考还是价值)呢?

如果机器是 64 位怎么办?

问候,

太平绅士

This is an efficiency question about 64 bit ints. Assuming I don't need to modify the value of a "int" parameter, should I pass it by value or reference.

Assuming 32 bit machine:

1) 32 bit int: I guess the answer is "pass by value" as "pass by reference" will have overhead of extra memory lookup.

2) 64 bit int: If I pass by reference, I only pass 32 bit address on the stack, but need an extra memory lookup. So which one of them is better (reference or value)?

What if the machine is 64 bit?

regards,

JP

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夜清冷一曲。 2024-10-09 05:06:53

按价值传递——肯定是这样。如果系统是 64 位,则意味着它复制 64 位字的速度非常快。

Pass by value - definitely. If the system is 64-bit it means it copies 64-bit word extremely fast.

彼岸花ソ最美的依靠 2024-10-09 05:06:53

即使在 64 位机器上,按值传递也更好(除了极少数例外),因为它可以作为寄存器值传递。

Even on a 64 bit machine pass by value is better (with some very few exceptions), because it can be passed as a register value.

无可置疑 2024-10-09 05:06:53

将它们作为 boost::call_traits::param_type 传递。该模板捕获了在受支持的平台上传递任何类型的最佳实践。因此,它在 32 位和 64 位平台上会有所不同,但您可以在任何地方使用相同的代码。它甚至可以在您还不知道确切类型的其他模板中使用。

Pass them as a boost::call_traits<int64_t>::param_type. This template captures the best practices for passing any type on the supported platforms. Hence, it will be different on 32 and 64 bits platforms, but you can use the same code everywhere. It even works inside other templates where you don't know the precise type yet.

夏日浅笑〃 2024-10-09 05:06:53

使用一点常识,

  1. 如果对象需要复杂的复制构造函数,那么可能值得通过引用传递(也就是说 - 很多 boost 的对象被设计为按值传递而不是引用,仅仅是因为内部实现是相当微不足道的)有一个奇怪的问题我还没有真正解决,std::string,我总是通过引用传递它......

  2. 如果您打算修改传入的值,请使用引用

  3. Else, PASS-BY-VALUE!

函数参数是否存在特定的性能瓶颈?否则,不要花太多时间担心哪个是最好的传递方式...

通过担心 int 如何传入进行优化就像在海里游泳一样...

Use a little common sense,

  1. if the object requires a complex copy constructor, it's probably worth passing by reference (saying that - quite a lot of boost's objects are designed to be passed-by-value rather than reference simply because internal implementation is quite trivial) There is one odd one which I haven't really worked out, std::string, I always pass this by reference...

  2. If you intend to modify the value that is passed in, use a reference

  3. Else, PASS-BY-VALUE!

Do you have a particular performance bottleneck with arguments to functions? Else, don't spend too much time worrying about which is the best way to pass...

Optimizing by worrying about how an int is passed in is like pi**ing in the sea...

童话 2024-10-09 05:06:53

为了便于讨论,让我们忽略优化器消除差异的小例子。假设您正在使用 Microsoft 的 Intel 64 位调用约定(与 Linux ABI 不同),那么您有 4 个 64 位寄存器用于传递这些值,然后您必须将它们压入堆栈。这显然更好。

对于 32 位应用程序,按值计算,它们会直接进入堆栈。通过引用可以将指针放入寄存器中(同样,在诉诸堆栈之前允许使用一些这样的寄存器)。我们可以在 g++ -O3 -S 的一些输出中这样做,通过值调用 f1(99) 并通过 const 引用调用 f2(101):

void f1(int64_t);
void f2(const int64_t&);

int main()
{
    f1(99);
    f2(101);
}

...

    pushl   0
    pushl   $99
    call    _Z2f1x    // by value - pushed two halves to stack

    leal    -8(%ebp), %eax
    movl    %eax, (%esp)
    movl    $101, -8(%ebp)
    movl    $0, -4(%ebp)
    call    _Z2f2RKx   // by const& - ugly isn't it!?!

然后,被调用的函数必须在首次使用之前检索(如果有)。被调用的函数可以自由地缓存寄存器中读取的值,因此只需要一次。使用堆栈方法,可以随意重新读取该值,因此不需要为该值保留寄存器。使用指针方法,如果需要暂时释放该寄存器以进行其他工作,则指针或 64 位值可能需要保存在更可预测的地方(例如,推送或另一个不太有用的寄存器),但 64 位值稍后再次需要 int 参数。总而言之,很难猜测哪个更快 - 可能取决于 CPU/寄存器使用/优化器/等,并且不值得尝试。

pst 建议的一个节点...

“效率”:( KISS。像传递其他该死的整数一样传递它。- pst

...不过,有时您将 KISS 应用于模板参数并使它们全部为 const T& 即使有些可能适合寄存器....

For argument's sake, lets ignore the trivial case of optimisers removing differences. Let's also say you're using Microsoft's Intel 64-bit calling conventions (which do differ from the Linux ABI), then you've got 4 64-bit registers for passing such values before you have to resort to pushing them on the stack. That's clearly better.

For a 32-bit app, by value and they'd go straight onto the stack. By-reference may instead put a pointer in a register (again, a few such register uses are allowed before resorting to the stack). We can this in some output from g++ -O3 -S, calling f1(99) by value and f2(101) by const reference:

void f1(int64_t);
void f2(const int64_t&);

int main()
{
    f1(99);
    f2(101);
}

...

    pushl   0
    pushl   $99
    call    _Z2f1x    // by value - pushed two halves to stack

    leal    -8(%ebp), %eax
    movl    %eax, (%esp)
    movl    $101, -8(%ebp)
    movl    $0, -4(%ebp)
    call    _Z2f2RKx   // by const& - ugly isn't it!?!

The called function would then have to retrieve before first usage (if any). The called function's free to cache the values read in registers, so that's only needed once. With the stack approach, the value can be reread at will, so the register need not be reserved for that value. With the pointer approach, either the pointer or 64-bit value may need to be saved somewhere more predictable (e.g. pushed, or another less useful register) should that register need to be freed up momentarily for some other work, but the 64-bit int parameter be needed again later. All up, it's hard to guess which is faster - may be CPU/register-usage/optimiser/etc dependent, and it's not worth trying.

A node to pst's advice...

"efficiency" :( KISS. pass it how you pass every other bloody integer. - pst

...though, sometimes you apply KISS to template parameters and make them all const T& even though some may fit in registers....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文