3 ms·
NVRO works by constructing the object once... (EDIT: detrino points out this is wrong, the object is not constructed first before passing, it is only a memory a
by eliasmacpherson 13y ago
NVRO works by constructing the object once...
(EDIT: detrino points out this is wrong, the object is not constructed first before passing, it is only a memory address that is passed, it's the return value that is constructed on to this address)
It is passed as a hidden argument to the function, assigning the return value to that argument passed in.
Prior to the NVRO, the object was constructed once, a temporary was constructed and then copy constructed to give the result.
You can test out the NVRO yourself by putting a printf in an object's constructor, and have the object returned from a function on to an object of the same type.
Stan Lipmann's Inside the C++ Object Model explained it best for me. NVRO applies to the vector object.
The difference here is that Stroustrup is talking about the elements of the vector, not the vector itself, and how the move semantics remove the need for constructing/copy constructing them.
- detrino 13y agoWhat you are talking about is really just the calling convention common on many machines. When you have a function returning a struct, what really happens is that the return address for the struct is passed as an extra argument. No construction of the struct happens prior to this, its just an address. Compilers are able to take advantage of this calling convention in many cases to elide copies, and the result is RVO/NRVO.
- eliasmacpherson 13y agoAre you alluding to some sort of hardware mechanism by mentioning machines? In what context are calling conventions machine dependent? The reason it's notable in C++ is because the code that would normally be called in the constructor is not called as many times as the person writing the code might expect. In C++ structs can have constructors, but usually have an empty default constructor supplied by the compiler, this is more of an issue when structs/classes have user supplied constructors. Here's an article giving more specifics of the history of NVRO from Stan Lipmann. Interestingly, NVRO was not added to Visual C++ til 2003, and Lipmann prefers NVRO off by default. I think I recall an NVRO flag in that compiler. NVRO was available in cfront and Zortech compilers in the early nineties. [1] [1] http://blogs.msdn.com/b/slippman/archive/2004/02/03/66739.aspx http://blogs.msdn.com/b/slippman/archive/2004/02/03/66739.as...
- detrino 13y agoThe calling convention your compiler is using is dependent on a number of things [1]. It is this calling convention that dictates how values are returned from a function, not whether or not RVO/NRVO is happening. Also, what is being passed as an extra argument, according to many calling conventions, it not really an already constructed object, but an address for an object to be constructed into. Under certain situations the compiler is able to elide copes, which as you pointed out, leads to your copy constructor to never be called at all, even if it has visible side effects. I think these are important distinctions and hoped pointing them out would be beneficial. [1] http://en.wikipedia.org/wiki/X86_calling_conventions http://en.wikipedia.org/wiki/X86_calling_conventions
- eliasmacpherson 13y agoYes, thanks for pointing the calling conventions out, I didn't really know what you were getting at. The hardware calling convention does dictate certainly what code the compiler can put out. If the compiler does not support NVRO and emits code that causes multiple copy/constructions it doesn't matter if the hardware supports more efficient behaviour. I edited my earlier comment with your correction, thanks.