Creating a temporary char buffer as a default function argument and binding an r-value reference to it allows us to compose statements on a single line whilst preventing the need to create storage on the heap.
const char* foo(int id, tmp_buf&& buf = tmp_buf()) // buf exists at call-site
Binding a reference/pointer to the temporary buffer and accessing it later yields undefined behaviour, because the temporary no longer exists.
As can be seen from the example app below the destructor for tmp_buf
is called after the first output, and before the second output.
My compiler (gcc-4.8.2
) doesn't warn that I'm binding a variable to a temporary. This means that using this kind of micro-optimisation to use an auto char buffer rather than std::string
with associated heap allocation is very dangerous.
Someone else coming in and capturing the returned const char*
could inadvertently introduce a bug.
1. Is there any way to get the compiler to warn for the second case below (capturing the temporary)?
Interestingly you can see that I tried to invalidate the buffer - which I failed to do, so it likely shows I don't fully understand where on the stack tmp_buf
is being created.
2. Why did I not trash the memory in tmp_buf
when I called try_stomp()
? How can I trash tmp_buf
?
3. Alternatively - is it safe to use in the manner I have shown? (I'm not expecting this to be true!)
code:
#include <iostream>
struct tmp_buf
{
char arr[24];
~tmp_buf() { std::cout << " [~] "; }
};
const char* foo(int id, tmp_buf&& buf = tmp_buf())
{
sprintf(buf.arr, "foo(%X)", id);
return buf.arr;
}
void try_stomp()
{
double d = 22./7.;
char buf[32];
snprintf(buf, sizeof(buf), "pi=%lf", d);
std::cout << "\n" << buf << "\n";
}
int main()
{
std::cout << "at call site: " << foo(123456789);
std::cout << "\n";
std::cout << "after call site: ";
const char* p = foo(123456789);
try_stomp();
std::cout << p << "\n";
return 0;
}
output:
at call site: foo(75BCD15) [~]
after call site: [~]
pi=3.142857
foo(75BCD15)