I said that hisStruct was an automatic data variable created on the stack and that it would go out of scope and be destroyed when the function returned. He said that classes and structs declared inside a function were created on the heap and were actually references, so they would not get destroyed until the reference count went to 0. To which I replied that hisStruct was not a reference because it was not declared using the '&' symbol.
So I rewrote his way, tested it, and was surprised that it worked! I thought I would get a bus trap, exception, or some other bad behavior.
I said that hisStruct was an automatic data variable created on the stack and that it would go out of scope and be destroyed when the function returned.
That is correct.
He said that classes and structs declared inside a function were created on the heap and were actually references, so they would not get destroyed until the reference count went to 0.
That is not correct.
However, the push_back function dynamically allocates memory for the object you insert on the list, you don't have to do it yourself. That's the reason the code suggested by your boss works. His explanation has nothing to do with it and neither is correct anyway.
EDIT: I want you to also notice that neither would your approach work if push_back didn't dynamically allocate memory. You see, the pointer you store is also a temporary variable and will be destroyed when your function returns. If push_back didn't dynamically allocate memory, and a list held references to objects instead of actual objects, you'd have to do something like this:
What happens is that hisStruct is copied, just like your myStruct pointer is copied into the list, so it doesn't matter that the local pointer/struct is destroyed at the end of the function.
References don't count anything in C++, they're just pointers with different syntax.
Maybe your boss was thinking of Java.
He said that classes and structs declared inside a function were created on the heap and were actually references, so they would not get destroyed until the reference count went to 0.
Is that literally what he said? Because that's one of the most retarded things I've ever heard.
Looking at this code, I can imagine that what he actually said was that the *_STRUCT_T instances were created inside list nodes that are allocated on the heap, and that the list that keeps these nodes from being destructed will exist as long as the program doesn't terminate.
In any case, yours may be more efficient, depending on how large a single *_STRUCT_T object is. I would possibly rewrite it like this:
//Note: Your identifiers seemed a bit schizophrenic on your second snippet. I'm
//assumming MY_STRUCT_T==HIS_STRUCT_T and myList==hisList.
void funcA(){
//2 copies being performed:
//MY_STRUCT_T myStruct = myList.front();
//myList.push_back(myStruct);
//No copies performed. Only a single object is constructed:
myList.push_back(MY_STRUCT_T());
}
void funcB(){
//Yet another useless copy:
//HIS_STRUCT_T myStruct=myList.front();
MY_STRUCT_T &myStruct=myList.front();
//...
myList.pop_front();
}
EDIT:
m4ster r0shi wrote:
if push_back didn't dynamically allocate memory
You can't implement a linked list without dynamic allocation. I'm not sure what difference your snippet makes other than leak memory.
Damn. You're right. I overestimated the smartness of the compiler. Not even list.resize(list.size()+1) calls a single constructor. Maybe MinGW is just being stupid.
Ok, that's what I meant. Of course, you need to at least allocate memory for the pointers to the stored objects, but you can implement a list that doesn't actually create objects.
Damn. You're right. I overestimated the smartness of the compiler. Not even list.resize(list.size()+1) calls a single constructor. Maybe MinGW is just being stupid.
Hm well, the compiler is not allowed to omit the copy. The only case where this is allowed by the C++ standard are function return values.
Still, for all compiler optimizations the same rule applies: as long as it doesn't change the behaviour of the program, everything is allowed. So that just means that any side effects that the copy constructor might have must be carried out.
gcc can call new to allocate a new list node and can then move the two numbers directly into the node. Formally, a copy of the temporary pair is constructed inside the node. But when optimizing, the temporary object just exists on paper, not in the actual code.