为何以下C++代码中的拷贝构造函数未被调用?
Ah, this is a classic case of Return Value Optimization (RVO)—specifically Named RVO (NRVO) here! Let me break down why your copy constructor isn’t being called, even though it looks like a copy should happen.
What’s NRVO, and How Does It Affect Your Code?
When your fun() function creates a named local object (ob) and returns it, modern compilers can optimize away the unnecessary copy operations that would normally occur:
- Without optimization:
fun()would constructob, copy it to a temporary object when returning, then copy that temporary toainmain(). That would trigger your copy constructor twice. - With NRVO enabled (the default in almost all compilers): The compiler skips both copies entirely. It directly constructs the
Testobject in the memory space allocated forainmain(). Soobinsidefun()is essentially just an alias fora—no copies needed, hence your copy constructor never runs.
Is This Allowed by the C++ Standard?
Absolutely! Since C11, compilers have been permitted to perform this optimization even if it changes observable behavior (like skipping copy constructor calls). In C17, RVO became mandatory for certain scenarios (including returning a named local object like your ob), so this behavior is consistent across modern compilers.
How to Force the Copy Constructor to Run
If you want to see the copy constructor execute, you can disable this optimization with compiler-specific flags:
- For GCC/Clang: Add
-fno-elide-constructorsto your compile command. - For MSVC: Use
/Zc:nrvo-to turn off NRVO, or/Odto disable all optimizations.
With these flags enabled, your count variable would increment twice (once for the return copy, once for initializing a), and you’d see the "sum" output from the copy constructor.
Quick Note on typeid(fun()).name()
The 4Test output you see is the mangled name of your Test class—some compilers prefix the class name with its length (4 characters for "Test") in their mangling scheme.
内容的提问来源于stack exchange,提问作者sumit kumar

