[comp.lang.c++] warning message from Sun C++ 2.0

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?