Prev: Trying to come to terms with typecasting operators
Next: C++ Middleware Writer version 1.10 is now on line
From: Martin B. on 25 Nov 2009 00:53 Goran wrote: > On Nov 24, 9:40 pm, George Neuner <gneun...(a)comcast.net> wrote: >> On Tue, 24 Nov 2009 10:13:09 CST, "Martin B." <0xCDCDC...(a)gmx.at> >> wrote: >> >>> Hi all. >>> ( Note that I've posted this to microsoft.public.vc.language a few days >>> ago, but didn't really get an answer there, so I hope someone may shed >>> some light on this in a more general context. ) >>> The Visual Studio compiler will never inline a funtion that returns an >>> unwindable object (e.g. std::string, CString, etc.) > (...) > That said, could this have something to do with compiler not knowing > the implementation of ~string, hence forcing a function call (not that > I see a connection)? As you've shown, when destructor is visible to > the compiler, all is indeed inline (but as usual with such examples, As I have asserted in my other reply, it does not matter if the dtor is visible. What was relevant in George's example was that MYPOINT did not have a dtor. If you add a dtor that does anything, get() won't be inlined. > one has to make sure that some unseen optimization doesn't play with > "expected" results). > Yes. These examples can easily be compiled with only the /Ob2 or /Ob1 switch and all other optimizations disabled, which is what I'm doing. cheers, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: George Neuner on 26 Nov 2009 20:29 On Wed, 25 Nov 2009 08:19:39 CST, "Martin B." <0xCDCDCDCD(a)gmx.at> wrote: >George Neuner wrote: >> On Tue, 24 Nov 2009 10:13:09 CST, "Martin B." <0xCDCDCDCD(a)gmx.at> >> wrote: > >> The first problem is, your code is not C++ but "managed C++", ... > >Incorrect. The security_cookie is generated by the /GS option (see: >http://msdn.microsoft.com/en-us/library/8dbf701c%28VS.80%29.aspx) adding >/GS- to the commandline will remove these references from the disassembly. My bad. I blanked on buffer check because I've been doing a lot of managed code recently and got used to seeing checks in disassemblies. >I have checked and your example does *not* contain an *unwindable* >object. MYPOINT has an empty dtor, because it contains only int members. >Adding a non-empty dtor to mypoint, for example: > MYPOINT::~MYPOINT() { > cout << "This is a non-empty dtor\n"; > } >will effectively prevent MYPOINT get() from being inlined. Miscommunication I think. I generally associate "unwind(able)" with use of exceptions, not just having a dtor. Since string and stream (as above) operations can throw and it's documented that throw code won't be inlined, I created code that didn't. Anyway, you are right that having a non-trivial dtor makes VC++ call the value object returning function rather than inlining it. Of course the obvious fix is (if possible) to return a reference to the object instead. I changed the code as follows to have a non-trivial dtor: static int constructs = 0; static int destructs = 0; class MYPOINT { public: int x, y, z; public: MYPOINT( int i, int j, int k ) { x = i; y = j; z = k; ++constructs; }; MYPOINT( MYPOINT& src ) { x = src.x; y = src.y; z = src.z; ++constructs; } ~MYPOINT() { ++destructs; } }; class Simple { public: MYPOINT s_; public: Simple() : s_(3,4,7) { } MYPOINT get() { return s_; } }; void testsimple() { Simple oSimple; MYPOINT s1( oSimple.get() ); cout << s1.z << endl; } VC++ compiles the explicit call to get() as you expected. However, GCC4 (MinGW) refuses to compile this code: test.cpp: In function 'void testsimple()': test.cpp:61: error: no matching function for call to 'MYPOINT::MYPOINT(MYPOINT)' and so does VC++ if you disable MS's language extensions: Error 1 error C2558: class 'MYPOINT' : no copy constructor available or copy constructor is declared 'explicit' test.cpp 61 test If you change get() to return MYPOINT&, then both compilers will inline the get() call in testsimple() regardless of the dtor. As for why the nontrivial dtor prevents inlining functions that value return objects, I can only speculate ... I haven't had occasion to look under the hood of a C++ compiler in quite a few years. My best guess is that it's too much trouble - in general - for the compiler to decide whether the temporary return object can be renamed and used directly or will need to be destructed in the caller - so there is a blanket edict against inlining such functions. The experts in comp.compilers are likely to know more (or at least guess better). George -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin B. on 27 Nov 2009 15:39 George Neuner wrote: > On Wed, 25 Nov 2009 08:19:39 CST, "Martin B." <0xCDCDCDCD(a)gmx.at> > wrote: >> I have checked and your example does *not* contain an *unwindable* >> object. MYPOINT has an empty dtor, because it contains only int members. >> Adding a non-empty dtor to mypoint, for example: >> MYPOINT::~MYPOINT() { >> cout << "This is a non-empty dtor\n"; >> } >> will effectively prevent MYPOINT get() from being inlined. > > Miscommunication I think. I generally associate "unwind(able)" with > use of exceptions, not just having a dtor. Since string and stream (as > above) operations can throw and it's documented that throw code won't > be inlined, I created code that didn't. > It has nothing to do with throw but with catch. A function such as inline int get_throwing_x() const { if(x > 0) return x; else throw std::runtime_error("x is not > 0!"); } will be inlined allright. What will be *not* inlined is a function containing a try: inline int get_try_x() const { try { s.empty(); return x-1; } catch(std::exception const& e) { return x+strlen(e.what()); } } .... will not be inlined. (see: http://msdn.microsoft.com/en-us/library/a98sb923.aspx) > Anyway, you are right that having a non-trivial dtor makes VC++ call > the value object returning function rather than inlining it. Of > course the obvious fix is (if possible) to return a reference to the > object instead. > (...) > That's why I provided a sample with a string return value. You should not return a reference to the objects internals. > > As for why the nontrivial dtor prevents inlining functions that value > return objects, I can only speculate ... I haven't had occasion to > look under the hood of a C++ compiler in quite a few years. > > My best guess is that it's too much trouble - in general - for the > compiler to decide whether the temporary return object can be renamed > and used directly or will need to be destructed in the caller - so > there is a blanket edict against inlining such functions. > Hmmm ... VC++ will always do RVO, i.e., there will never be a temporary object for the string object, even if all optimizations are turned off. So I can't imagine how the temporary could pose a problem here. > The experts in comp.compilers are likely to know more (or at least > guess better). > Thanks. I guess it's off to a third NG with the question :-) cheers, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: George Neuner on 1 Dec 2009 12:16 On Sat, 28 Nov 2009 02:39:57 CST, "Martin B." <0xCDCDCDCD(a)gmx.at> wrote: >George Neuner wrote: > >> My best guess is that it's too much trouble - in general - for the >> compiler to decide whether the temporary return object can be renamed >> and used directly or will need to be destructed in the caller - so >> there is a blanket edict against inlining such functions. > >Hmmm ... VC++ will always do RVO, i.e., there will never be a temporary >object for the string object, even if all optimizations are turned off. >So I can't imagine how the temporary could pose a problem here. The compiler always _tries_ to do RVO, but there are plenty of cases where it is not possible - one of which is passing an object by value where a reference is expected (a Microsoft extension). If you do something like: string G() { ... } string F( string &in ) { string out; ...; return out; } string x = F( G() ); you'll find that the return value from F() is optimized as expected but for F(G()) the return value from G() is a hidden stack temporary, a reference to which is then passed to F(). George -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin B. on 1 Dec 2009 20:05 George Neuner wrote: > On Sat, 28 Nov 2009 02:39:57 CST, "Martin B." <0xCDCDCDCD(a)gmx.at> > wrote: > >> George Neuner wrote: >> >>> My best guess is that it's too much trouble - in general - for the >>> compiler to decide whether the temporary return object can be renamed >>> and used directly or will need to be destructed in the caller - so >>> there is a blanket edict against inlining such functions. >> Hmmm ... VC++ will always do RVO, i.e., there will never be a temporary >> object for the string object, even if all optimizations are turned off. >> So I can't imagine how the temporary could pose a problem here. > > The compiler always _tries_ to do RVO, but there are plenty of cases > where it is not possible - one of which is passing an object by value > where a reference is expected (a Microsoft extension). > > If you do something like: > > string G() { ... } > string F( string &in ) { string out; ...; return out; } > > string x = F( G() ); > > you'll find that the return value from F() is optimized as expected > but for F(G()) the return value from G() is a hidden stack temporary, > a reference to which is then passed to F(). > Cheers, that's an interesting point. One might argue though that the hidden stack temporary "belongs" to the F(.) call and thus does say nothing about RVO. :-) That is, given: string G() { string s; ... returns s; } string F(string &in) { string out; ... returns out; } and given two different code versions: void t3() { // uses MS extension string s; s = F( G() ); } void t4() { string s; string tmp(G()); s = F( tmp ); } this will essentially generate the same assembly for t3 and t4 so I'm really not sure if we can and should say that "RVO does not happen". br, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: Trying to come to terms with typecasting operators Next: C++ Middleware Writer version 1.10 is now on line |