In this case, does the compiler re-create and re-destroy the object at each iteration?
Semantically, yes. A compound literal appearing at block scope has automatic storage duration associated with the innermost containing block. Its lifetime ends when execution of that block terminates for any reason.
But that doesn't put many constraints on the under-the-hood behavior of the implementation.
You seem to be concerned about the cost of allocation and deallocation inside the loop, but allocation and deallocation of automatic objects is typically very fast. Often effectively free. On a stack-based machine, the memory used, if any, will be on the stack, and the same location will ordinarily be re-used on every loop iteration.
The main difference between the two alternatives you present is that semantically, the former requires the object to be initialized on every loop iteration, whereas the latter must initialize it only once. Only if the compiler determines that the literal is not modified within the body of the loop, including indirectly by some_function(), can it consider lifting the initialization out of the loop to treat your first variation as if it were the second.
If you want to encourage the compiler to make that assumption then you could declare some_function as ...
void some_function(const my_struct *value);
... and define the literal as ...
(const my_struct) { /* ... */ }
. If for some reason that's not semantically viable for you, then the optimization you're hoping for is inappropriate in the first place.
I prefer the first syntax as it is less verbose, but I am also worried about performance.
Such a concern is premature. Any performance difference between your two variations is likely to be too small too measure. Even if your structure were very large, so that you might actually be able to observe the cost of initializing it, you don't know whether that cost -- if even incurred -- is large enough to justify micro-optimization without measuring the program's performance and profiling it to see where it's spending its time.
In general, write clean and clear code, using appropriate, efficient algorithms. Use available language features to express your intent in as much detail as you can. Enable compiler optimizations, and then don't worry about performance until you identify an actual performance problem.
const. So both a compiler must assume both the functionf(const T *)and the functionf(T *)may modify the pointed-to data, unless it can see their definitions or some extension informs it about the nature of the function.f(T *p)andf(const T *p)may be used to modify the memory pointed to byp. Per the standard, theconstqualifier on a pointed-to type serves only advisory role: The implementation must issue a diagnostic if code attempts to modify aconst-qualified lvalue. But it is permitted to convert the pointer toT *and use* (T *) pas a non-const-qualified lvalue, provided the object was not originally defined asconst. The compiler must assumef(const T *p)may change*p.pdoes not modify memory pointed to byp(in the absence of any other information, such as seeing the function definition), and whether the parameter is declaredT *orconst T *does not alter that. You were not only engaging with OP when you wrote your comment; every user may read it, and the statement misinforms them.