From: Vidar Hasfjord on 11 Dec 2006 22:17 peter koch larsen wrote: > Worse is the negations: > I "never" write [if (!t)] when t is not bool. The irony is that the latter "false" case is safer than the "true" case, because you can explicitly control the conversion to bool via operator overloading for the type involved (hence avoid unwanted implicit conversions). This leads to the strange {if (!!t)} idiom to test the "true" case. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: James Kanze on 12 Dec 2006 09:36 PeteK wrote: > James Kanze wrote: > > PeteK wrote: > > > if ( p ) > > > rather than > > > if( p != NULL ) > > > with a system-defined vaule they couldn't (portably) do this. > > Sure you can. The definition of how a pointer is converted to a > > bool is that the results are true if the pointer is non null. > > (That doesn't mean that I approve of "if (p)". Say what you > > mean, and mean what you say, IMHO. if requires a logical > > boolean, and it is very poor programming practice to give it > > anything else.) > As I said in another reply, this is an artifact of numerics decaying to > bools (which I also dislike, but which was necessary when there was no > boolean type) and the null pointer being equivalent to zero. We basically agree, but historically... This is an artifact of C deriving from B, which didn't have any types. Everything was a machine word. (The language was obviously developed on a word addressed machine, which didn't have bytes.) You could, for example, initialize a variable with a floating point value, and do integer arithmetic on it (or vice versa); the results we likely unmeaningful, but that was your problem, not the compiler's. The distinction between floating point arithmetic and integral arithmetic was made by your choice of operator, not by the type of the variable. If you don't have types, of course, you don't have a boolean type either, so you need some convention. > If the > latter hadn't been true then I very much doubt that a null pointer > would ever have been treated as false. > > > But, as you say, it's just a weird rule anyway. > > It's an aspect of C++ that I don't like. Far too many implicit > > conversions for my taste. But there's not much we can do about > > it without breaking too much code. (IIRC, the authors of the > > bool proposal originally proposed deprecating the implicit > > conversions of pointers, and I think of numeric types as well, > > to bool. They withdrew this part of the proposal in face of the > > resistence it encountered.) > Understandable, given the amount of code already written. However I > wish that bool had been in from the start, in which case there would > have been a perfect opportunity to remove the implicit conversion. Presumably, if bool had been there from the start, there never would have been an implicit conversion. And there would have been some sort of real null pointer value, which couldn't be taken for an int. Whenever I think of these issues, I'm reminded of a quote from Sir Walter Scott: "Oh, what a tangled web we weave, when first we practice to deceive." It's not really a fair evaluation, since there was never any intent to deceive, and in fact, the original decisions were quite understandable in the context they were made. But the fact remains that certain parts of the language are based on false premises (e.g. that a pointer can be true or false), and the result really is a tangled web. -- James Kanze (GABI Software) email:james.kanze(a)gmail.com Conseils en informatique orient�e objet/ Beratung in objektorientierter Datenverarbeitung 9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34 -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: James Kanze on 12 Dec 2006 09:35 Mirek Fidler wrote: > > Which is where our experience differs. For me, most classes are either > > on the stack, in a collection or embedded in another class. Only a > > small number of classes require the use of smart pointers and in the > IME, no objects require the use of smart pointers (nor GC). Both GC > and/or smart_ptrs are bad idea. You can always find the scope where the > object instance logically belongs. Don't be silly. When the saleman creates an order, there's no program scope at which it could possibly be placed. -- James Kanze (GABI Software) email:james.kanze(a)gmail.com Conseils en informatique orient�e objet/ Beratung in objektorientierter Datenverarbeitung 9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34 -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Gerhard Menzl on 12 Dec 2006 09:39 David Abrahams wrote: > Gerhard Menzl <clcppm-poster(a)this.is.invalid> writes: >> Your choice of terms was at least >> misleading: someone unfamiliar with the C++ exception mechanism could >> easily interpret it as describing a compile-time check, which is >> precisely what C++ does not offer. To avoid this confusion, >> especially when comparing C++ with Java, which does have static >> checks, I think it is important to distinguish between "cannot throw" >> and "will abort if it throws". > > What's the difference between a function that "will abort if it > throws" and one that "might abort (for whatever reason)?" There is a difference between a compile-time guarantee and an abort at runtime. That C++ does not offer the former may be obvious to you, which is probably why you didn't find the statement misleading, but it could easily lead less experienced readers of this group to believe there is such a thing as compile-time exception specification checking. I don't quite understand why you are so opposed to my attempt of clarification. -- Gerhard Menzl Non-spammers may respond to my email address, which is composed of my full name, separated by a dot, followed by at, followed by "fwz", followed by a dot, followed by "aero". [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: James Kanze on 12 Dec 2006 09:36
PeteK wrote: > James Kanze wrote: > > PeteK wrote: > > My experience is that almost no classes have a logical owner. > > Most classes which have a deterministic lifetime manage that > > lifetime themselves. When I'm using garbage collection in C++, > > I'd guess that about 90% of the deletes are "delete this". > Which is where our experience differs. For me, most classes are either > on the stack, in a collection or embedded in another class. In terms of number of classes, you're probably right. In terms of number of objects, however, it's less sure. Things like the characters in a string, for example, can't be on the stack, since they have variable size. > Only a small number of classes require the use of smart > pointers and in the end even these are bound to the lifetime > of a single class created to run the application. The word > "delete" usually only turns up in comments. Or in a few special classes, such as smart pointers? I do have entity objects which have more or less complicated state, and for which one of the states means that no further operations are legal on the object. > [...] > > "abc" is "abc", regardless of scope or context. You're letting > > implementation constraints of C++ color your conception. > Now you're losing me. Ultimately all objects are just an ordered > collection of chars, so you're basically saying that "everything is > always alive, regardless of scope or context". No. Some objects have identity, others are just "values". The value "abc", like the value 5, exists forever. It existed before your program started running, and it will exist after it stops. At some point in the execution of your program, you create an instance of this value, i.e. you allocate memory for it, and put the correct bits in that memory to represent it. At some later point, this instance ceases to exist. In the case of an integer value, we create many, many instances, copying the bits at the drop of a hat. No pointers and no dynamic allocation and deallocation are involved. But that's only because 1) the size of an integer is fixed (in C++---it's an artificial restriction), and 2) copying is cheap. In the case of a string of text, the size of the representation isn't known before hand, and copying it could be expensive. So we allocate dynamically to create the first instance, and we copy pointers, rather than the object---with regards to the code, in many ways, the pointer is the value. > > > In C++ we can extend that logical lifetime by using > > > smart pointers and the like, but there is still a defined point when > > > the object is logically dead. > > Yes. When no other object can possibly access it. > No! > int * f() > { > int > x = 3; > return &x; > } > x logically dies at the end of the function, but you can still access > it (if you're talking about the memory location it occupies, and in the > context of zombies I can't see what other definition you can use). You haven't understood what I'm saying. What I'm saying is that the value 3 hasn't ceased to exist. In the above code, you've given x an identity; it's no longer a simple value. And of course, you're creating a circular argument. You're argument is basically that all objects have a deterministic lifetime because that's the way C++ currently works, and that C++ is right to work that way because all objects have a deterministic lifetime. In other languages, your code above would be perfectly legal; it would be in Java for anything but a basic type, e.g. if you used Integer instead of int. The example I'm trying to point out is something like: int f() { return 3 ; } Now write the same code where 1) the return value is a string, and 2) it is read from a file, or calculated in some way that we don't know the length before hand. Or write it simply replacing int with a BigInteger, of undefined length. All of the solutions I know in C++ involve either deep copy (expensive), or some sort of reference counting (tricky, and expensive if it has to be thread safe). > In C++ something is logically dead when it's destructor is > called. The fact that you've got live pointers to it doesn't > mean it's alive, it means you've probably got an error in your > program. By definition, at the language level. C++ requires us to create a deterministic lifetime for all objects, even if the design doesn't require it. That's what I'm arguing against. > [...] > > True, but in practice, you don't have to worry about objects > > which aren't logically dead, but which are inaccessible, because > > the program doesn't need them any more. > Unless these objects contain precious resources. Which in practice they don't (except memory). How can a value contain a resource? -- James Kanze (GABI Software) email:james.kanze(a)gmail.com Conseils en informatique orient�e objet/ Beratung in objektorientierter Datenverarbeitung 9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34 -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |