按值返回的对象分配的位置
Where the object returned by value is allocated
问题是:当按值返回时,临时对象在哪里分配? 即,在堆栈上,在动态分配的内存中 - 编译器在这种情况下做什么?
我正在深入研究 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 new
,void* 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
- 0xC0000005:访问冲突写入位置0xCDCDCDCD动态分配错误
- 是否可以将值分配给移出位置?
- 创建一个类来访问和指定向量类型,并构建一个获取位置并为其分配区域的类
- 在尝试使用CUDA分配内存时,我遇到了访问冲突写入位置错误
- 为什么动态分配的两个变量的内存位置不是连续的?
- 为字符串中的每个字符(不是字符位置!)分配唯一的索引
- 只读位置'__result.std::_Rb_tree_const_iterator<_Tp>::operator*<long long int>()'分配错误
- 每次我分配新的位置时,都会隐式地称为destuructor
- 在动态分配矩阵上的访问违规读数位置
- 如何专用/分配自定义内存位置,以便可以在C 中编辑该位置
- C 中的内存模型:为什么在同一内存位置分配了结构中的两个整数
- 动态分配存储数据在堆中的随机位置中
- 在为矩阵分配值时访问冲突写入位置0x00000000
- 分配浮点时访问违规位置(0x0000000000000170)
- 为什么在C 中的堆中的垃圾位置无法重新分配
- 使用set_union合并两组时,只读位置的分配
- 是STD :: Vector,由于其分配运算符移动其成员的位置,因此是一种非常规类型
- 将字符串分配到动态数组位置时出错
- 指向已解除分配位置的指针 是未定义的行为吗?
- 实现自定义malloc(),可以在c++中跟踪分配位置