Prev: _CrtIsValidHeapPointer Assertion in C++/CLI Application Debug mode.
Next: Error LNK2028 unresolved token / LNK2019 Unrevolved external symbol
From: Gerry Hickman on 12 Aug 2007 17:24 Hi Doug, Would it be possible for you to post a more detailed example of your code? I understand my pointer version, and the "Charles Wang" 'references' version, but I didn't quite understand your version. Regarding the count of instances, I'm not against it, but in theory I can grab this after the function returns, however, there is an issue of "reserving" (as you pointed out) if the number of classes was large. Either way, I think all the code we've been discussing will be more elegant than the official DevCon Device Classes enum sample code! I'm actually designing a low-level version of the CIM_MediaAccessDevice WMI class. This will get all block level devices such as CD-ROM, Data Stick, Floppy, PhysicalDisk etc. Doug Harrison [MVP] wrote: > On Fri, 10 Aug 2007 22:47:34 +0200, "Bo Persson" <bop(a)gmb.dk> wrote: > >> Doug Harrison [MVP] wrote: >> :: On Fri, 10 Aug 2007 08:59:05 +0200, Ulrich Eckhardt >> :: <eckhardt(a)satorlaser.com> wrote: >> :: >> ::: Gerry Hickman wrote: >> :::: Doug Harrison offered this example: >> :::: >> :::: ----- example start ----- >> :::: >> :::: I would use pass-by-reference to avoid this needless cost, e.g. >> :::: >> :::: vector<string>::size_type >> :::: void GetDeviceClasses(vector<string>& guids) >> :::: { >> ::: [...] >> :::: returns guids.size(); >> :::: } >> ::: >> ::: Funny. Talking about needless costs and then returning redundant >> ::: data - the size can be retrieved from the vector. >> :: >> :: What's "funny" is to compare returning a vector<string> by value to >> :: returning its size, the latter being as close to a free operation >> :: as there is, both in terms of complexity and exception safety. Not >> :: to mention, returning the size is a useful thing to do. >> >> How do you know that it is useful? Always? > > Often, after using a function with a name such as "GetDeviceClasses", a > programmer wants to know how many such classes were found; he may be > interested in the exact number, or he may just treat it as a boolean. > Provided one can indicate errors in some other way, there's no reason not > to return the number of items that were found, elements read, etc. > >> Assuming that we are trying to optimize a time-critical piece of code, >> why return a value that isn't asked for? Especially as it is also >> returned as a part of the guids parameter. > > The code in question populates a vector<string>, and judging by its name, > probably enumerates the registry. I don't understand how anyone could worry > about the efficiency of returning vector::size() in this context. > > (Granted, if you were talking about std::list, you might have a very, very > tiny point, but to date, I'm unaware of anyone making vector::size worse > than O(1).) > >> It is also often not considered good style to have both a return value >> and out-parameters. > > This is not an example of bad style. > > (Q: What do you think this interface is equivalent to, if anything? To help > you focus, you can limit yourself to standard functions.) > >> If you need to, you can have several >> out-parameters, and not single out one of them as a return value. > > Yes, you can do that if you need to. > -- Gerry Hickman (London UK)
From: Ulrich Eckhardt on 13 Aug 2007 02:47 Doug Harrison [MVP] wrote: > On Fri, 10 Aug 2007 08:59:05 +0200, Ulrich Eckhardt > <eckhardt(a)satorlaser.com> wrote: >>Gerry Hickman wrote: >>> Doug Harrison offered this example: >>> >>> ----- example start ----- >>> >>> I would use pass-by-reference to avoid this needless cost, e.g. >>> >>> vector<string>::size_type >>> void GetDeviceClasses(vector<string>& guids) >>> { >>[...] >>> returns guids.size(); >>> } >> >>Funny. Talking about needless costs and then returning redundant data - >>the size can be retrieved from the vector. > > What's "funny" is to compare returning a vector<string> by value to > returning its size, the latter being as close to a free operation as there > is, both in terms of complexity and exception safety. > Not to mention, returning the size is a useful thing to do. Nah, it increases the complexity for the reader. My question would be how the returnvalue differs from the size. Is it perhaps only the number of elements added to the vector? No, seriously, I'd prefer a straight-forward interface _without_ redundancy. >>Anyway, why would you write anything but clear code unless you first >>determined that it's a bottleneck? Just return the vector by value. > > I don't know what's "funnier"; suggesting the code I presented isn't > "clear", recommending returning a vector<string> by value, or equating > returning a vector<string> by value with returning size(). The clearest thing is IMHO returning the result of a function by using 'return'. Now, concerning efficiency: a) vector const& v = my_function(); b) vector v; your_function(v); Which of those is more efficient? You claim that it's b), but using a modern compiler they can be equivalent and a) is much clearer because you see immediately that there is something returned. You might even be able to drop the reference and it would remain the same code. I think it's about where you draw the line. If it was not a vector of strings but a string, would you return it by value? I would. If it contained the content of a whole file? I wouldn't. How about vector<char> or vector<int>? Or vector<some_POD>? I can't tell you where one of these or the original example degrades in performance so far that you can't afford passing it by value anymore, but until I know that I stay with the clearest possible code. > You could almost take it on the road, I think. :) I'm not familiar with that term... Uli
From: Gerry Hickman on 13 Aug 2007 08:13 Hi Ulrich, >> but when I came to actually code this, I ran into some problems. > > This doesn't help. What problems? I was confused by Doug's example, I'd copied it literally vector<string>::size_type void GetDeviceClasses(vector<string>& guids) { guids.clear(); // If you can estimate n, reserve can eliminate reallocations. // guids.reserve(n); ... returns guids.size(); } I guessed 'returns' should be a comment, but the first two lines didn't make sense with void following vector<string>::size_type, I guess I was supposed to _replace_ void with vector<string>::size_type, seems obvious now. >> void PopulateStrings(vector<string> * guids) >> { >> guids->clear(); >> guids->push_back("test1"); >> guids->push_back("test2"); >> } > > While this code will work, there is one thing I object to: in C++, where you > have references, a pointer[1] means to me that something is optional, i.e. > passing zero is okay, but you don't mean that. Still, you must handle that > case, so either you just return (making it a non-error), throw an exception > (making it a runtime error) or use assert() (making it a programmer's > error). Does this only apply to the 'pointer' version, or does it apply to the 'references' version too? -- Gerry Hickman (London UK)
From: Gerry Hickman on 13 Aug 2007 08:15 Thanks Charles, I tested your code, it works great, and is also very easy to read. Charles Wang[MSFT] wrote: > Hi Gerry, > Could you please let us know what the problems you ran into if you used > Doug's suggestion? > > It should also work if you use reference as following: > =================================== > vector<string> guids; > PopulateStrings(guids); > cout << "Count of guids is now " << guids.size(); // prints 2 > > void PopulateStrings(vector<string> & guids) > { > guids.clear(); > guids.push_back("test1"); > guids.push_back("test2"); > } > ================================== > > Best regards, > Charles Wang > Microsoft Online Community Support > ===================================================== > When responding to posts, please "Reply to Group" via > your newsreader so that others may learn and benefit > from this issue. > ====================================================== > This posting is provided "AS IS" with no warranties, and confers no rights. > ====================================================== > > > -- Gerry Hickman (London UK)
From: Gerry Hickman on 13 Aug 2007 08:18
Gerry Hickman wrote: > Would it be possible for you to post a more detailed example Sorry, I understand it now. -- Gerry Hickman (London UK) |