4

这个问题不是这个问题或其他类似问题的重复。这个问题是关于在初始化和使用清除结构。


更新

在阅读了您的前几条评论后,我想澄清我的问题:

  • 如何强制 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:警告:C6262:函数使用堆栈的 '144400' 字节:超过 /analyze:stacksize '16384'.. 此分配用于编译器生成在第 162 行临时用于“struct BitmapBuffer”。考虑将一些数据移动到堆中。

我认为会发生以下情况:

  • 在栈上构造一个临时对象
  • 临时对象被复制到对象变量

我想看到那里发生的默认初始化。在我看来,编译器应该能够优化堆栈分配。但显然(根据警告)编译器没有这样做。我的问题是:如何强制编译器忽略堆栈分配? 我现在已经开始用以下代码替换这些地方:

std::memset(&ms, 0, sizeof(ms));
4

1 回答 1

1

由于my_struct是可简单复制的,编译器应该能够发出memset调用而不是创建一个临时然后分配它,但这不是强制性的。

Placement new 表达式将解决您的问题:它使用提供的构造函数在预先分配的地址构造一个对象。例如,new(&ms) my_struct{}给出与 相同的语义ms = {}。应该my_struct有一个非平凡的 Destructor,一个显式调用ms.~my_struct()必须在放置 new 之前。供参考:新表达式

我建议不要以正常方式使用这种技术。这是一种“黑魔法”低级 C++。好的编译器应该使用memset.

顺便说一句,oh_my全局变量不会在堆栈上分配临时变量,因为它是在编译时初始化的常量。

于 2018-12-11T19:58:35.737 回答