按值返回的对象分配的位置

Where the object returned by value is allocated

本文关键字:分配 位置 对象 返回      更新时间:2023-10-16

问题是:当按值返回时,临时对象在哪里分配? 即,在堆栈上,在动态分配的内存中 - 编译器在这种情况下做什么?

我正在深入研究 C++03 中移动构造函数习惯用法中的底层逻辑,如更多C++习语/移动构造函数中所述,有趣的部分是如何返回对象:

struct foo {
    int values[100];
    ...
};
foo func() {
    foo ret;
    ... // assign value to ret
    return ret;
}
int main() {
    foo a(func());
    ...
    return 0;
}

return ret;a(func) 之间的点显然包含堆栈清理和进一步的复制构造,但是临时对象在传递到复制构造函数之前存储在哪里?也许,我在搜索结果中监督了答案,但仍然找不到解释。

编辑:

好吧,这个例子可能看起来过于简单了。在实际应用程序中,我们可以编写如下内容:

class Command {
public:
    Command();
    Command(const Command &);
    ...
private:
    CommandResponseType mResponseType;
    quint64    mId;
    QString    mName;
    quint16    mTypeCode;
    QDateTime  mDatetime;
    TParamList mParams;
};

这样的类不是 POD,编译器可能不会通过简单地在堆栈上分配值来优化副本构造Command a(someInstanceOfOtherClass.getCommand("foo"));。至少,涉及QString,QDateTime和TParamList的复制构建。

如果我理解正确,getCommand() __thiscall调用约定,它要求被调用方自行清理堆栈。逻辑解决方案是在内存中分配结果并返回一个指针。我将尝试不同的场景并查看组装。

一种可能性是,如果编译器足够聪明,将其优化为分配(在main()的堆栈帧内)和移动,则根本没有临时对象。如果有,那很可能也在堆栈上,但为什么不检查生成的程序集呢?

当我编写foo a(func());时,调用了结构构造函数,它基本上是一个函数。这需要论点func().因此,代码将首先计算func()并将返回值推送到堆栈。现在foo()将此值作为参数。实现提供商可以在这里自由地进行任何类型的优化。如果我错了,请纠正我。

如何在堆栈上构造对象的简单示例是以非分配形式隐式使用operator newvoid* operator new (std::size_t size, void* ptr) throw()

class Foo {
public:
    Foo();
    Foo(const Foo &);
    ~Foo();
private:
    // data members
    ...
}
void bar() {
    Foo f1;
    // // Allocate sufficient memory on stack:
    // char f1[sizeof(Foo)];
    // // Call operator new on this memory and execute Foo's constructor
    // // with (this == f1):
    // operator new (sizeof(Foo),f1) Foo();
    ...
    // Or «non-optimized» case, with copy-constructor involved:
    Foo f2 = Foo();
    // char f2[sizeof(Foo)];
    // {
    //     // tmp is constructed as in the previous case:
    //     char tmp[sizeof(Foo)];
    //     operator new (sizeof(Foo),tmp) Foo();
    //     // And then f2 is constructed using Foo's copy-constructor:
    //     Foo::Foo(f2 /*this*/, tmp)
    // }
    // // Here, tmp must be destructed and popped from stack.
}

链接:

http://en.wikipedia.org/wiki/Return_value_optimization