c++ - 如何强制 MSVC 编译器省略大型临时对象的堆栈分配?

标签 c++ visual-c++ initialization stack-allocation

这个问题不是 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/

相关文章:

java - java.lang.SecurityManager 中的初始化字段有什么用?

c++ - g++ 4.8.2 在列表方法参数默认初始化时出错

C++ Windows : Handle application external crash into the program

c - 在函数内部时如何不重新分配静态变量

c++ - 我如何打开这个应用程序是 visual studio 以便我可以运行代码?

c++ - 在c函数中传递字符串时发出警告

c++ - self 背后的理论和用法是什么,包括 C 和 C++ 中的源文件?

c++ - C/C++ 字符串文字中的未知元字符?

php - 当您可以用 <<< 和结束分隔符填充字符串时,这叫做什么?

c++ - 我在控制台中的数据显示顺序错误