Removing const for benefit of assignment operator

  • Thread starter Joost Ronkes Agerbeek
  • Start date
J

Joost Ronkes Agerbeek

Should I remove const from a private member just for the sake of the
assignment operator?

I have a class that looks something like this.

class Foo
{
public:
Foo(const std::string& description) : _description(description) {}

private:
const std::string _description;
};

The compiler warns me that it cannot generate an assignment operator,
because _description is const. _description will never change unless you
assign a new object to the Foo-instance. Does that warrant making
_description non-const.

Somehow I see oldFoo = newFoo more as assigning a new object to the
oldFoo-identifier than as changing the oldFoo-object. Is that a poor grasp
of concept on my side?

Thanks in advance.
 
E

E. Robert Tisdale

Joost said:
Should I remove const from a private member
just for the sake of the assignment operator?

I have a class that looks something like this.

class Foo {
public:
Foo(const std::string& description): _description(description) { }
private:
const std::string _description;
};

The compiler warns me that it cannot generate an assignment operator,
because _description is const. _description will never change
unless you assign a new object to the Foo-instance.
Does that warrant making _description non-const.
cat Foo.cc
#include <string>
#include <iostream>

class Foo {
private:
const std::string _description;
public:
friend
std::eek:stream& operator<<(std::eek:stream& os, const Foo& f) {
return os << f._description;
}
Foo& operator=(const Foo& f) { return *this; }
Foo(const std::string& description):
_description(description) { }
};

int main(int argc, char* argv[]) {
Foo a(std::string("a"));
std::cout << a << std::endl;
a = Foo(std::string("b"));
std::cout << a << std::endl;
return 0;
}
g++ -Wall -ansi -pedantic -o Foo Foo.cc
./Foo a
a


Somehow I see oldFoo = newFoo more as assigning a new object to the
oldFoo-identifier than as changing the oldFoo-object.
Is that a poor grasp of concept on my side?

Yes.
 
H

Howard

Joost Ronkes Agerbeek said:
Should I remove const from a private member just for the sake of the
assignment operator?

I have a class that looks something like this.

class Foo
{
public:
Foo(const std::string& description) : _description(description) {}

private:
const std::string _description;
};

The compiler warns me that it cannot generate an assignment operator,
because _description is const. _description will never change unless you
assign a new object to the Foo-instance. Does that warrant making
_description non-const.

Somehow I see oldFoo = newFoo more as assigning a new object to the
oldFoo-identifier than as changing the oldFoo-object. Is that a poor grasp
of concept on my side?

Yes. :) An assignment is a copy operation. The assignment operator needs
to copy into each member of your object from the right-hand-side object, and
it can't do that in this case because the string is const. If you're going
to allow assignment to your object at all, then you'll have to be able to
change _description. (As you said, it WILL change if you assign to it.)
Thus, it shouldn't be const.

-Howard
 
H

Howard

E. Robert Tisdale said:
#include <string>
#include <iostream>

class Foo {
private:
const std::string _description;
public:
friend
std::eek:stream& operator<<(std::eek:stream& os, const Foo& f) {
return os << f._description;
}
Foo& operator=(const Foo& f) { return *this; }

How does this help anything? No assignment is taking place here. In fact,
f is completely ignored! I don't think that's what he wanted... do you?
Foo(const std::string& description):
_description(description) { }
};

int main(int argc, char* argv[]) {
Foo a(std::string("a"));
std::cout << a << std::endl;
a = Foo(std::string("b"));

But since operator= simply returns *this, which is just a itself, how can
this line constitute an assignment of the temporary to a? The variable a
shouldn't change at all here, right?
 
E

E. Robert Tisdale

Howard said:
E. Robert Tisdale said:
#include <string>
#include <iostream>

class Foo {
private:
const std::string _description;
public:
friend
std::eek:stream& operator<<(std::eek:stream& os, const Foo& f) {
return os << f._description;
}
Foo& operator=(const Foo& f) { return *this; }


How does this help anything? No assignment is taking place here.
In fact, f is completely ignored!
I don't think that's what [Joost] wanted... do you?

I don't think Joost knows what he wanted
and I don't think that you know either.
Foo(const std::string& description):
_description(description) { }
};

int main(int argc, char* argv[]) {
Foo a(std::string("a"));
std::cout << a << std::endl;
a = Foo(std::string("b"));


But since operator= simply returns *this, which is just a itself,
how can this line constitute an assignment of the temporary to a?
The variable a shouldn't change at all here, right?

I's common practice to include a [const] string in an object
which describes the *variable* and not the value which it contains.
For example:

Foo name(std::string("name"));

Usually, the object contains other [private] data members
which represent the [mutable] value of the variable
so the class developer must provide an *explicit*
assignment operator which assigns a new value to the variable
without changing the description of the variable itself.
 
C

Cy Edmunds

Joost Ronkes Agerbeek said:
Should I remove const from a private member just for the sake of the
assignment operator?

I have a class that looks something like this.

class Foo
{
public:
Foo(const std::string& description) : _description(description) {}

private:
const std::string _description;
};

The compiler warns me that it cannot generate an assignment operator,
because _description is const. _description will never change unless you
assign a new object to the Foo-instance. Does that warrant making
_description non-const.

Somehow I see oldFoo = newFoo more as assigning a new object to the
oldFoo-identifier than as changing the oldFoo-object. Is that a poor grasp
of concept on my side?

Thanks in advance.

--
Joost Ronkes Agerbeek
Yellow Wood Studios
http://www.yellowwoodstudios.com/
http://www.ronkes.nl/

I can't see any reason to declare _description as const. You have done your
duty by declaring it private. If you write

Foo x("abc");
Foo y("def");
y = x;

wouldn't you expect y._description to be "abc" now? If so, it would be
illogical and self defeating to declare it const.
 
E

E. Robert Tisdale

Cy said:
I can't see any reason to declare _description as const.
You have done your duty by declaring it private.

You are assuming that
_description is the value of the object.
const data members are common in C++ objects.
They are often used as appears in this case
to describe the variable itself and *not* its value.
 
C

Cy Edmunds

E. Robert Tisdale said:
You are assuming that
_description is the value of the object.

No, I am assuming that _description is part of the object's abstract state.
const data members are common in C++ objects.

Maybe in objects *you* design. I don't actually recall ever using a const
data member.
They are often used as appears in this case
to describe the variable itself and *not* its value.

If a member variable is part of the abstract state of the object then
assignment should change it. If it is not part of the abstract state of the
object it should be static. I might see exceptions to this is if you are
doing some sort of debugging or logging of history, etc., but I certainly
don't find that such scenarios are particularly common in practice.
 
P

Peter Koch Larsen

E. Robert Tisdale said:
You are assuming that
_description is the value of the object.
const data members are common in C++ objects.
They are often used as appears in this case
to describe the variable itself and *not* its value.

I've never created a class with a const member variable. Never. Neither have
i ever seen one in one of the textbooks, I've read. So to say that they are
common certainly is far out.

/Peter
 
H

Howard

E. Robert Tisdale said:
Howard said:
E. Robert Tisdale said:
cat Foo.cc
#include <string>
#include <iostream>

class Foo {
private:
const std::string _description;
public:
friend
std::eek:stream& operator<<(std::eek:stream& os, const Foo& f) {
return os << f._description;
}
Foo& operator=(const Foo& f) { return *this; }


How does this help anything? No assignment is taking place here.
In fact, f is completely ignored!
I don't think that's what [Joost] wanted... do you?

I don't think Joost knows what he wanted
and I don't think that you know either.

Well, I think I do, given the original question. From the original post:

"_description will never change unless you
assign a new object to the Foo-instance"

This implies that if you do an assignment, you get a new value for
_description. That's what the "unless" means.

-Howard
 
J

Joost Ronkes Agerbeek

I can't see any reason to declare _description as const. You have done
your duty by declaring it private. If you write

Foo x("abc");
Foo y("def");
y = x;

wouldn't you expect y._description to be "abc" now? If so, it would be
illogical and self defeating to declare it const.

Goodness, there's a clear example if ever I saw one. :) Thanks for clearing
that up. Now I wonder if there is ever a situation in which you would
actually want to make a member const, but I see that there is some
discussion on that subject already.
 
J

Joost Ronkes Agerbeek

Yes. :) An assignment is a copy operation. The assignment operator
needs to copy into each member of your object from the right-hand-side
object, and it can't do that in this case because the string is const. If
you're going to allow assignment to your object at all, then you'll have
to be able to change _description. (As you said, it WILL change if you
assign to it.) Thus, it shouldn't be const.

-Howard

Thanks, I think I get it now. I got a bit carried away trying to be const
correct.
 
J

Joost Ronkes Agerbeek

How does this help anything? No assignment is taking place here.
In fact, f is completely ignored!
I don't think that's what [Joost] wanted... do you?

I don't think Joost knows what he wanted
and I don't think that you know either.
Well, that's partly true. After all, I wouldn't ask the question if I had
perfect understanding of the subject. :) What I was thinking of, was a
property of the object that gets set at object construction and that will
not change during the objects life-time. When the object gets copy, the
property gets copied also. Something like: when a child is born, its gender
is decided for the duration of its life and if you clone the child, the
clone has the same gender.
 
E

E. Robert Tisdale

Joost said:
How does this help anything? No assignment is taking place here.
In fact, f is completely ignored!
I don't think that's what [Joost] wanted... do you?

I don't think Joost knows what he wanted
and I don't think that you know either.

Well, that's partly true. After all, I wouldn't ask the question if I had
perfect understanding of the subject. :) What I was thinking of, was a
property of the object that gets set at object construction and that will
not change during the objects life-time. When the object gets copy, the
property gets copied also. Something like: when a child is born, its gender
is decided for the duration of its life and if you clone the child,
the clone has the same gender.

You are confusing the copy constructor and the assignement operator.

Foo brother(std::string("boy"));
Foo sister(std::string("girl"));
Foo bubba(brother); // [default] copy constructor
sister = brother; // [explicit] assignment operator

Do you want your assignment operator
to turn your sister into a boy?
 
J

Joost Ronkes Agerbeek

You are confusing the copy constructor and the assignement operator.
Foo brother(std::string("boy"));
Foo sister(std::string("girl"));
Foo bubba(brother); // [default] copy constructor
sister = brother; // [explicit] assignment operator

Do you want your assignment operator
to turn your sister into a boy?

Good point. Actually, I don't know whether I'd want that; I guess the
metaphore breaks down there. :) But now I know where my confusion comes
from. Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top