gpt4 book ai didi

struct - 使用单个引用传递结构是否有任何隐藏成本?

转载 作者:行者123 更新时间:2023-12-02 09:04:17 24 4
gpt4 key购买 nike

我最近正在阅读this关于 D 中的结构和类的文章,作者曾评论说

...this is a perfect candidate for a struct. The reason is that it contains only one member, a pointer to an ALLEGRO_CONFIG. This means I can pass it around by value without care, as it's only the size of a pointer.

这让我思考;真的是这样吗?我可以想到一些情况,在这些情况下,相信您“免费”传递一个结构可能会存在一些隐藏的陷阱。

考虑以下代码:

struct S
{
int* pointer;
}

void doStuff(S ptrStruct)
{
// Some code here
}

int n = 123;
auto s = S(&n);
doStuff(s);

当 s 传递给 doStuff() 时,单个指针(包装在结构中)真的全部传递给函数吗?在我的脑海中,似乎还会传递任何指向成员函数的指针以及结构的类型信息。

当然,这对于类来说不是问题,因为它们始终是引用类型,但是结构体的按值传递语义向我表明,任何额外的“隐藏”数据(例如上面描述的)都将传递给函数以及结构体的 int 指针。这可能会导致程序员认为他们正在传递一个(假设是 64 位机器)8 字节指针,而实际上他们传递的是一个 8 字节指针以及其他几个指向函数的 8 字节指针,加上对象的类型信息的字节数。粗心的程序员会在堆栈上分配比预期多得多的数据。

我在这里追逐阴影,还是在传递带有单个引用的结构时,这是一个有效的问题,并且认为您正在获取一个伪引用类型的结构? D 中是否有某种机制可以防止这种情况发生?

最佳答案

我认为这个问题可以推广到包装 native 类型。例如。您可以创建一个 SafeInt 类型,它包装和行为类似于 int,但会抛出任何整数溢出情况。

这里有两个问题:

  1. 编译器可能无法像 native 类型那样优化您的代码。

    例如,如果您要包装 int,则可能会实现重载算术运算符。足够智能的编译器将内联这些方法,并且生成的代码将与 int 的代码没有什么不同。在您的示例中,愚蠢的编译器可能会以某种笨拙的方式编译取消引用(例如,获取结构体的起始地址,添加指针字段的偏移量(即 0),然后取消引用)。

    此外,在调用函数时,编译器可能决定以其他方式传递结构(例如由于优化不佳或 ABI 限制)。这可能会发生,例如如果编译器不关注结构体的大小,并以相同的方式处理所有结构体。

  2. D 中的struct 类型确实可能具有隐藏成员(如果您在函数中声明它)。

    例如,以下代码有效:

    import std.stdio;

    void main()
    {
    string str = "I am on the stack of main()";

    struct S
    {
    string toString() const { return str; }
    }

    S s;
    writeln(s);
    }

    它之所以有效,是因为 S 保存了一个指向 main() 堆栈帧的隐藏指针。您可以通过在声明前添加 static 前缀(例如 static struct S)来强制结构体不具有任何隐藏指针。

关于struct - 使用单个引用传递结构是否有任何隐藏成本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13319822/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com