francis@sunquest.UUCP (Francis Sullivan) (12/20/89)
I have just started learning C++, and was experimenting with a string class for practice. Using g++ 1.34.2, I don't get warning messages with the following program, but I do with Sun C++ 2.0. ############# file nstr.cc ############ class Str { public: Str(Str&); Str(char *); Str(); ~Str(); Str& operator= (Str& s1); Str friend operator+ (Str& s1, Str& s2); }; main (int argc, char *argv[]) { Str c; for (int i = 1; i < argc; i++) c = Str(argv[i]) + " " + c; } // eof of nstr.cc now using Sun C++ 2.0 CC -g -c nstr.cc CC +g nstr.cc: "nstr.cc", line 13: warning: temporary used for non-const Str & argument "nstr.cc", line 13: warning: temporary used for non-const Str & argument ########## The program works fine, but I want to be able to do operations like above without getting the warning message. Any solutions besides delaring temporary strings for " " and the strings built from argv? -- Francis Sullivan Senior Programmer/Analyst Sunquest Information Systems Tucson, AZ email: francis@sunquest.com or sunquest!francis@arizona.edu or {uunet,arizona}!sunquest!francis
ark@alice.UUCP (Andrew Koenig) (12/20/89)
In article <1286@sunquest.UUCP>, francis@sunquest.UUCP (Francis Sullivan) writes: > class Str { > public: > Str(Str&); > Str(char *); > Str(); > ~Str(); > Str& operator= (Str& s1); > Str friend operator+ (Str& s1, Str& s2); > }; > The program works fine, but I want to be able to do operations like above > without getting the warning message. Any solutions besides delaring temporary > strings for " " and the strings built from argv? People who use references as arguments usually do so for one of two reasons: (1) they want to be able to modify the argument. (2) they want to avoid copying the argument for efficiency and do not intend to modify it. If you're using a reference for reason (1), it's bad news for you to pass a temporary, because anything you change will be discarded with the temporary. Thus the warning, which future releases will make into an error. If your motivation is (2), you should announce your intention not to modify the argument by using a reference to a constant: class Str { public: Str(const Str&); Str(const char *); Str(); ~Str(); Str& operator= (const Str& s1); Str friend operator+ (const Str& s1, const Str& s2); }; Note also the use of `const char*' rather than `char*' -- you probably don't intend to modify the argument of the Str constructor. -- --Andrew Koenig ark@europa.att.com
jimad@microsoft.UUCP (Jim Adcock) (12/21/89)
In article <1286@sunquest.UUCP> francis@sunquest.UUCP (Francis Sullivan) writes: >I have just started learning C++, and was experimenting with a string class for >practice. Using g++ 1.34.2, I don't get warning messages with the following >program, but I do with Sun C++ 2.0. [...] >class Str { > public: > Str(Str&); > Str(char *); > Str(); > ~Str(); > Str& operator= (Str& s1); > Str friend operator+ (Str& s1, Str& s2); >}; ... I added the keyword "const" to all explicet parameters of all member functions of Str and the warnings went away. Without the "const" keyword, the compiler assumes the member functions could modify the referred-to objects, and may introduce temporaries to protect against this presumed modification. Declare parameters "const" if they will not be modified by the routine using them. Declare member functions "const" if they do not modify "this." Not only is this an important part of documenting a routine, it can also lead to significantly better generated code.
jimad@microsoft.UUCP (JAMES ADCOCK) (12/22/89)
In article <10264@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes: >one of two reasons: > > (1) they want to be able to modify the argument. > > (2) they want to avoid copying the argument for efficiency > and do not intend to modify it. > >If you're using a reference for reason (1), it's bad news for >you to pass a temporary, because anything you change will be >discarded with the temporary. Thus the warning, which future >releases will make into an error. Hm, I can see where this might deserve a warning, but there would seem to be many situations where you want to modify a temporary. One [weak] example is that tired old warhorse complex number dimorph re/im or mag/pha. The temp gets added to something so its changes itself from mag/pha to re/im. Its not "constant" [or is it? -- I disagree with people who believe "const" should not imply constant structure] so you [or at least I] wouldn't want to declare it constant. But then "future releases" would mark this an error. Perhaps a better example would be say a linked string class where op+ causes a temporary structure of linked strings to be built up -- the links are temporaries that must be modified to add more strings to the linked list. But the linked string representation is itself temporary -- eventually the linked list of strings is flattened to a linear string, and the temporary links are discarded. Why should this approach deserve to be called an "error?" In general, marking temps that change as "errors" would seem to make temps second class citizens, and force classes to be coded to correctly handle both cases: 1) objects that can change, and 2) those who can't. On the other hand, maybe ark can argue that temps are now considered to be of flavor "const" and the new restrictions on temps are to be considered a requirement to make all our classes work right in both the "const" and "non-const" cases? But there would seem to be reasonable, every day class designs where it just doesn't make sense to consider any members of that class "const." Any Thoughts?