This question is not a duplicate of this one or other similar questions. This question is about clearing a struct after it has been initialized and used already.
Update
After reading the first few of your comments I would like to clarify my question:
- How can I compel the MSVC compiler to elide the large stack allocation?
I've updated the title, text and the code below to clarify this.
I've recently started to compile my projects with the /GS
, /sdl
and /analyze
compiler options. (Microsoft Visual C++ 2015) With these options, the compiler correctly warns about questionable code constructions. However, I've come across some warnings that I've always thought to be good C++ style.
Please have a look at the following example code:
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);
}
I've been told that the standard C++ way of clearing a struct is the following one:
ms = {};
With the /analyze
option, the compiler warns about this in the following way (example):
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.
I think the following happens:
- a temporary object is constructed on the stack
- the temporary object is copied to the object variable
I would like to see something like the default initialization happening there. In my opinion the compiler should be able to optimize the stack-allocation away. But apparently (according to the warning) the compiler does not do this. My question is this: How can I compel the compiler to elide the stack-allocation? I have now started to replace these places with the following code:
std::memset(&ms, 0, sizeof(ms));
Since
my_struct
is trivially copyable, compilers should be able to place amemset
call instead of creating a temporary and then assign it, but it is not mandatory.A Placement new expression will solve your problem: it constructs an object at a preallocated address using the supplied constructor. For example,
new(&ms) my_struct{}
gives the same semantics asms = {}
. Shouldmy_struct
have a Non trivial Destructor, an explicit call toms.~my_struct()
must precede the placement new. For reference: new expressionI suggest to not use this technique in a normal fashion. It is kind of 'black magic' low level C++. Good compilers should optimize using
memset
.By the way, the
oh_my
global variable doesn't allocate a temporary on the stack because it is Constant initialized at compile time.