这个问题不是 this one 的重复问题或其他类似问题。这个问题是关于在初始化和使用后清除一个结构。
更新
在阅读了您的前几条评论后,我想澄清一下我的问题:
- 如何强制 MSVC 编译器省略大堆栈分配?
我更新了标题、文本和下面的代码以阐明这一点。
我最近开始使用/GS
、/sdl
和/analyze
编译器选项编译我的项目。 (Microsoft Visual C++ 2015) 使用这些选项,编译器可以正确警告有问题的代码结构。但是,我遇到了一些我一直认为是好的 C++ 风格的警告。
请看下面的示例代码:
struct my_struct {
char large_member[64000];
};
void do_something_else(my_struct & ms)
{
// the intent of the next line is to "clear" the ms object
ms = {}; // <-- here the compiler claims the large stack allocation
// ... do some more work with ms
}
my_struct oh_my = {}; // construction, apparently no large stack allocation
int main()
{
// ...
// do something with the oh_my object
//
do_something_else(oh_my);
}
有人告诉我清除结构的标准 C++ 方法如下:
ms = {};
使用 /analyze
选项,编译器会以下列方式(示例)对此发出警告:
C:\Dev\MDS\Proj\MDSCPV\Vaps_Common_lib\camber_radar.cpp:162: warning: C6262: Function uses '144400' bytes of stack: exceeds /analyze:stacksize '16384'.. This allocation was for a compiler-generated temporary for 'struct BitmapBuffer' at line 162. Consider moving some data to heap.
我认为会发生以下情况:
- 在栈上构造一个临时对象
- 临时对象被复制到对象变量
我希望看到类似默认初始化的事情发生在那里。在我看来,编译器应该能够优化堆栈分配。但显然(根据警告)编译器不会这样做。 我的问题是:如何强制编译器省略堆栈分配? 我现在已经开始用以下代码替换这些地方:
std::memset(&ms, 0, sizeof(ms));
最佳答案
由于 my_struct
是可简单复制的,编译器应该能够放置一个 memset
调用而不是创建一个临时的然后分配它,但是这不是强制性的。
Placement new 表达式 将解决您的问题:它使用提供的构造函数在预分配地址构造一个对象。例如,new(&ms) my_struct{}
提供与 ms = {}
相同的语义。如果 my_struct
有一个 Non trivial Destructor,对 ms.~my_struct()
的显式调用必须在放置 new 之前。供引用:new expression
我建议不要以正常方式使用此技术。它是一种“黑魔法”低级 C++。好的编译器应该使用 memset
进行优化。
顺便说一句,oh_my
全局变量不会在堆栈上分配一个临时变量,因为它在编译时被常量初始化。
关于c++ - 如何强制 MSVC 编译器省略大型临时对象的堆栈分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53725492/