Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


c++ w/vs2010 and temporaries


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 achild   Crossbones+   -  Reputation: 1945

Like
0Likes
Like

Posted 07 February 2012 - 10:45 AM

Ok, here is a question I am absolutely clueless on. Hopefully someone here can help! At work we have a function like so:
bool GetFolder(String &folderpath, const String &caption = "", HWND hOwner = NULL) {
... bla bla bla ...
bi.lpszTitle = caption.IsEmpty() ? 0 : caption;
... bla bla bla ...


Now, String has the following members (this is of course not an exhaustive listing)
INLINE String(const String &Text) : InternalString_(Text.InternalString_) { }
INLINE operator const wchar_t*() const { return InternalString_.c_str(); }
INLINE const wchar_t *GetPtrW() const { return InternalString_.c_str(); }


And in the above, InternalString_ is just a std::wstring.

Now, here's my question, if anyone has any wonderful insight! In vs2008, the above line of code in GetFolder does as I expected, and we get a pointer to the string stored inside the object actually referenced by the caption variable. However, in vs2010, a temporary String object is created, which we get the pointer to the string inside it, which of course vanishes into oblivion immediately following that line of code, giving us crazy nonsensical strings and other wonderful unsafe behavior.

Can anyone tell me why it is creating a temporary? If I use "GetPtrW" or an explicit cast it works fine... but there are a lot of places in code that use the implicit cast.

Sponsor:

#2 achild   Crossbones+   -  Reputation: 1945

Like
0Likes
Like

Posted 07 February 2012 - 04:16 PM

On the chance that anyone was interested in the problem above

And the answer is: There wasn't enough information in my original post! (of course I didn't realize this at the time)

Missing information: The String class here also has implicit conversion from many built in types (such as int) to String using other
constructors in String (which I didn't list above).

So then...

What is happening here is not exactly what I thought previously. That ternary operator can't change types, so it is returning a String (the choices being String, or integer). In order to do this, it is implicitly creating a temporary String, which gets assigned a copy of "caption", or a converted value 0. That temporary string is where the cast to LPCTSTR happens, and of course disappears after the statement has executed.

By changing the "0" to "(LPCTSTR)0" or some such thing (better yet, "(LPCTSTR)nullptr"), we end up with the ternary operator outputting a temporary LPCTSTR, which instead of implicitly converting the 0 or the nullptr, it implicitly converts the "caption" variable to const wchar_t * type, which is what we originally wanted.

Phew.

#3 Cornstalks   Crossbones+   -  Reputation: 6991

Like
0Likes
Like

Posted 07 February 2012 - 04:20 PM

Thanks for posting the follow up. I was curious, and thought an additional constructor might be involved, but wasn't aware of how the ternary operator might be affecting this.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#4 achild   Crossbones+   -  Reputation: 1945

Like
0Likes
Like

Posted 07 February 2012 - 04:26 PM

Thanks for posting the follow up. I was curious, and thought an additional constructor might be involved, but wasn't aware of how the ternary operator might be affecting this.

The ironic things is that if the "convenient" constructors of String for converting integers and floats and such to String weren't there, the compiler would have complained that it can't convert the integer 0 to a String, and we would have been good to go.

#5 Zoner   Members   -  Reputation: 232

Like
0Likes
Like

Posted 08 February 2012 - 03:07 PM


Thanks for posting the follow up. I was curious, and thought an additional constructor might be involved, but wasn't aware of how the ternary operator might be affecting this.

The ironic things is that if the "convenient" constructors of String for converting integers and floats and such to String weren't there, the compiler would have complained that it can't convert the integer 0 to a String, and we would have been good to go.


More accurately they should have been written to have explicit constructors, which segways into the C++ standard should have had explicit be the default behavior.

#6 Aardvajk   Crossbones+   -  Reputation: 6255

Like
0Likes
Like

Posted 09 February 2012 - 02:04 AM

More accurately they should have been written to have explicit constructors, which segways into the C++ standard should have had explicit be the default behavior.


This is more a good example of why a string class should not have an operator const char*. There are good reasons that std::string lacks this.

blah = (test ? 0 : str.c_str());

would not have exhibited these problems. Plus the whole plethora of other gotchas that arise from implicitly converting what is essentially a very temporary buffer into a normal pointer to char.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS