operator== and vector confusion - c++

I'm having some trouble keeping objects in a vector, and I think I need to do something with the operators.
std::vector<Foo> vec;
Foo a = Foo();
vec.push_back(a);
...
if(std::find(vec.begin(), vec.end(), a) < vec.end()) {
// Found
} else {
// Not found
}
Foo needs operator== to compile, I do this
bool Foo::operator==(const Foo& rhs) {
return this == &rhs;
}
But from what I understand, vec.push_back, is going to make a copy of the Foo object, so my == will return false.
Hence, whenever I get to the searching, it is never found.
What's the right thing to do here? I'm hoping to avoid switching to a vector of pointers.

Change the implementation of Foo::operator== to compare the member variables of Foo for equality instead of checking identity. For example:
bool Foo::operator==(const Foo& rhs) const {
return get_a() == rhs.get_a()
&& get_b() == rhs.get_b(); // and so on
}
Note that this can also be a const function since it should not modify any member variables and should be usable on const instances of Foo.

Your operator== implies that identity is defined by its location in memory, but the fact that you are appending values to a vector and hoping for equality says that identity is NOT defined by location.
If for some reason you don't have an identity definition based on any other members, you can add a unique identifier to your Foo objects, can compare that identifier in your code:
bool operator==(const Foo &rhs)
{
return this->m_id == rhs.m_id;
}

There is really nothing you can do, std::vector<> (or rather most standard containers) makes copies on insertions. If equality of two Foo objects is really defined by their addresses being equal the only thing you can do is to store pointers in the std::vector<>. If you want to store pointers in the std::vector<> I'd recommend storing smart-pointers instead like std::shared_ptr<>, std::unique_ptr<>.
If Foo's is too heavy to copy you can make Foo Move-only in C++11 or you can make it move only in C++03 using boost::containers::vector and boost::move.
Probably it is just easier to change the operator==() to compare the member variables instead.

Related

Pointer Objects comparison using pointer expression in cpp

I create a two pointer object of a class 'myclass'
myclass *obj1,*obj2;
can I compare these two objects using comparison operator and pointer expression i.e *obj1==*obj2
If yes, how does it happen?
If not, why isn't his allowed?
If yes, how does it happen?
If not, why isn't his allowed?
In short the answer will be yes if you have defined a suitable operator == function for comparing myclass instances and no if you have not defined a suitable operator == function.
There are two ways to declare an operator == function - as a member function of the MyClass class or as a non-member function (sometimes called a global function or free function).
Declaring a MyClass member function might look something like this...
class MyClass
{
public:
bool operator == (const MyClass &rhs) const
{
bool result{ false };
// calculate result;
return result;
}
// ... etc ...
};
Given the statement if (*obj1 == *obj2) the member function above would be called on the *obj1 instance (i.e., this would refer to *obj1) while the *obj2 instance would be passed as the argument to the parameter rhs.
Alternatively, the equality comparison operator for MyClass could be declared as a non-member (aka global) function...
bool operator == (const MyClass &lhs, const MyClass &rhs)
{
bool result{ false };
// calculate result;
return result;
}
In this case, given the statement if (*obj1 == *obj2) the function above would be called with the *obj1 instance passed as the argument to the lhs parameter and the *obj2 instance passed as the argument to the rhs parameter.
You cannot declare both a member function and a non-member function operator == using the same signature. The compiler wouldn't be able to decide which one to call!
Whichever technique you use to declare an operator == function, the "calculate result" code can be absolutely anything that makes sense for your particular class, so long as it returns true or false.
Typically you would compare the various members of the two objects and return true if those members held the same values. But you might not compare all members. Consider, for example, the following Book class...
class Book
{
public:
std::string Title;
std::string Author;
std::string Isbn;
// ... etc ...
};
You might decide that operator == should return true only if the two instances have equal ISBN values because different editions of a book like The Hitchhiker's Guide To The Galaxy should be considered different. Alternatively you might decide that two Book instances are equal if they have the same Title and Author because paperback and hardback editions of the Guide might have different ISBNs but they're still (in some sense) the same book.
Finally(!) it should be noted that while the sample code above uses const MyClass & as the type for the rhs parameter C++ does not require that the rhs parameter be the same type as the lhs parameter.
Normally it would be of course, and defining an operator == function that compared two dissimilar types would be likely to confuse readers and could cause problems for programmers using your class. But, as is often the case, if you think you know what you are doing, C++ won't get in your way.
If you'd like to read more about comparison operators you might find http://en.cppreference.com/w/cpp/language/operator_comparison interesting.
Yes, this will work, but only if you've overloaded the == operator for your class. If you have, then == will invoke the appropriate operator== method, which implements the equality test for your class. In other words, it's up to you to define what equality means for your class.
== operator on pointers will compare their numeric address and hence determine if *obj1 and *obj2 points to the same object or not.
bool operator==(const myclass &obj2); // in this method, see if obj2 is equal to *this.
The code you are suggesting will work only if myclass defines operator==.
And as Jeremy Friesner pointed out, you need to beware of invalid pointers, in particular the value NULL (or nullptr).
So what you really want is:
if ((obj1 != nullptr) && (obj2 != nullptr( && (*obj1 == *obj2)) ...
I would also recommend changing those identifiers to ptr1 and ptr2, as "obj1" and "obj2" would imply to the average reader that they are objects rather than pointers to objects. Or myclsptr1 and myclsptr2, as an indication to the reader of what sort of thing they point to. Or, better yet, names that indicate what their purpose is in this part of the program.
can I compare these two objects using comparison operator and pointer expression i.e *obj1==*obj2
Synactically speaking, you can do that only if the operator is defined for the class. You can do that by overloading the operator== function, which can be a member function or a non-member function.
It will work at run time only if obj1 and obj2 point to valid objects.
If obj1 and obj2 point to valid objects, *obj1 == *obj2 will work just like if you had
MyClass o1;
MyClass o2;
and used o1 == o2
1.Pointer to a class is similar-to pointer to a Structure where if you want to compare you have to access and compare each and every member.
2.You can compare obj1==obj2(which compares address) but if you want to compare two objects *obj1==*obj2 you have to overload "==" operator in your "myclass" like this:::
bool operator==(const myclass& b) {//Compare methods or variables of both objects and return result bool(true/false)

Can I get away with putting auto_ptr in a STL container?

I am inheriting an interface, and implementing a virtual function that is supposed to do some work on a list of dynamically allocated objects. The first step is to remove duplicates from the list based on some custom equivalence criteria:
class Foo { /* ... */ };
struct FooLess
{
bool operator()(const Foo *lhs, const Foo *rhs);
}
struct FooEqual
{
bool operator()(const Foo *lhs, const Foo *rhs);
}
void doStuff(std::list<Foo*> &foos)
{
// use the sort + unique idiom to find and erase duplicates
FooLess less;
FooEqual equal;
foos.sort( foos.begin(), foos.end(), less );
foos.erase(
std::unique( foos.begin(), foos.end(), equal ),
foos.end() ); // memory leak!
}
The problem is that using sort + unique doesn't clean up the memory, and the elements to be erased have unspecified values after unique, so I cannot perform the cleanup myself before eraseing. I was considering something like this:
void doStuff(std::list<Foo*> &foos)
{
// make a temporary copy of the input as a list of auto_ptr's
std::list<auto_ptr<Foo>> auto_foos;
for (std::list<Foo>::iterator it = foos.begin(); it != foos.end(); ++it)
auto_foos.push_back(auto_ptr<Foo>(*it));
foos.clear();
FooLess less; // would need to change implementation to work on auto_ptr<Foo>
FooEqual equal; // likewise
auto_foos.sort( auto_foos.begin(), auto_foos.end(), less );
auto_foos.erase(
std::unique( auto_foos.begin(), auto_foos.end(), equal ),
auto_foos.end() ); // okay now, duplicates deallocated
// transfer ownership of the remaining objects back
for (std::list<auto_ptr<Foo>>::iterator it = auto_foos.begin();
it != auto_foos.end(); ++it)
{ foos.push_back(it->get()); it->release(); }
}
Will this be okay, or am I missing something?
I am not able to use C++11 (Boost might be possible) or change the function signature to accept a list of straightforward Foos.
To put an object into a standard container the object needs value semantics (the standard says "copy assignable" and "copy constructable"). Among other things, that means the copy constructor and assignment operator needs to create a copy of an object (leaving the original intact)
The auto_ptr copy constructor does not do that. Instead, the copy constructor and assignment operator transfer ownership of the pointer.
As a consequence, it is not possible for a standard container to contain an auto_ptr.
A lot of implementations (as in compiler and standard library) have the standard containers and/or auto_ptr coded so attempting to have a container of auto_ptr's will trigger a compiler error. Unfortunately, not all implementations do that.
There are generally the following methods you can use in C++98:
Define some pointer that will do what std::auto_ptr can't do. There was an old version of that thing, which contained an additional field of type bool that marked ownership. It was marked mutable, so it could be modified also in the object being read from when copying. The object was deleted at the end only if owned was true. Something like:
==
template <class T> class owning_ptr
{
T* ptr;
mutable bool owns;
public:
void operator =(T* src) { ptr = src; owns = true; }
owning_ptr(const owning_ptr& other)
{
// copy the pointer, but STEAL ownership!
ptr = other.ptr; owns = other.owns; other.owns = false;
}
T* release() { owns = false; return ptr; }
~owning_ptr() { if ( owns ) delete ptr; }
/* ... some lacking stuff ..*/
};
You may try out boost::shared_ptr
Instead of std::unique, you may try to do std::adjacent_find in a loop. Then you'll just find all elements that are "the same" as by your equal. If there's more than one element, you will erase them in place (you are allowed to do it because it's a list, so iterators remain valid).

Remove an object in a std::vector by value

I would like to remove an object from a stl vector if it is present.
class test
{
vector<Objects> myvector;
public:
test();
removeTest(Objects);
}
test::removeTest(Objects aObject)
{
myvector.erase(remove(myvector.begin(), myvector.end(), aTest),myvector.end());
}
However, whenever I try to compile this, I get the following error:
no match for 'operator=='
This only occurs if I use an iterator through a vector of objects of type 'Objects'. I can get it to work for the case of looking for an integer then removing this.
Anyone know why I am getting these errors? And am I using the correct method to remove an object from a stl vector of objects by value?
no match for 'operator=='
Error says it all. You need to provide an equality comparison for your Object class, std::remove can't otherwise know how to compare your objects to determine which ones need to be removed.
For example:
struct Object {
int i;
std::string s;
bool operator==(const Object& rhs) const {
return i == rhs.i && s == rhs.s;
}
};
It worked for integers because equality comparison between integers is built-in. Not so for user-defined types.
With that, this:
void test::removeTest(const Object& aObject)
// ^^^^ ^^^^^^^^^^^^^
{
myvector.erase(
remove(myvector.begin(), myvector.end(), aObject),
// ^^^^^^^
myvector.end()
);
}
Should do exactly what you want. Note that you were missing a return type for removeTest (I'm assuming you want void) and you should take the object you want to remove by reference-to-const to avoid the unnecessary copy.

c++: implementing the equal method - how to make sure the given object is not the same reference as this?

Consider the following code snippet:
bool SomeObject::equal(const SomeObject& rhs) const
{
if (this == &rhs)
{
return true;
}
// check the state
}
The problem with this code is that SomeObject might override operator& (or someone might add it in the future), which in turn may break this implementation.
Is it possible to test whether rhs and *this are the same object without being at the mercy of operator& implementation?
If you want to get the actual address of the object and ignore overloaded & operators then use std::addressof
bool SomeObject::equal(const SomeObject& rhs) const
{
if (this == std::addressof(rhs))
{
return true;
}
// check the state
}
Reference: http://en.cppreference.com/w/cpp/memory/addressof
There's a std::addressof function in C++11 which should do what you want.
If you wanted to implement it yourself, you could use casting to another type:
(SomeClass*)&reinterpret_cast<char&>(rhs)
However, I wouldn't bother; a const equals function should work fine for identical parameters.
What if you just removed that condition entirely? How often is someone going to compare an object to itself? If you usually need to inspect all the data members anyway, then this simple comparison just wastes time in the average case. As long as nothing bad happens when the two objects are physically the same (and your function is const, so you should be fine), then what's the harm in doing a little extra work in the rare case?
Just pass a pointer to SomeObject instead of a reference, so you don't need the & operator anymore.
It would like this then:
bool SomeObject::equal(const SomeObject* rhs) const
{
if ( this == rhs )
{
return true;
}
//...
}

C++: STL troubles with const class members

It is an open ended question.
Effective C++. Item 3. Use const whenever possible. Really?
I would like to make anything which doesn't change during the objects lifetime const. But const comes with it own troubles. If a class has any const member, the compiler generated assignment operator is disabled. Without an assignment operator a class won't work with STL. If you want to provide your own assignment operator, const_cast is required. That means more hustle and more room for error. How often you use const class members?
EDIT: As a rule, I strive for const correctness because I do a lot of multithreading. I rarely need to implemented copy control for my classes and never code delete (unless it is absolutely necessary). I feel that the current state of affairs with const contradicts my coding style. Const forces me to implement assignment operator even though I don't need one. Even without const_cast assignment is a hassle. You need to make sure that all const members compare equal and then manually copy all non-const member.
Code. Hope it will clarify what I mean. The class you see below won't work with STL. You need to implement an assignment for it, even though you don't need one.
class Multiply {
public:
Multiply(double coef) : coef_(coef) {}
double operator()(double x) const {
return coef_*x;
}
private:
const double coef_;
};
You said yourself that you make const "anything which doesn't change during the objects lifetime". Yet you complain about the implicitly declared assignment operator getting disabled. But implicitly declared assignment operator does change the contents of the member in question! It is perfectly logical (according to your own logic) that it is getting disabled. Either that, or you shouldn't be declaring that member const.
Also, providing you own assignment operator does not require a const_cast. Why? Are you trying to assign to the member you declared const inside your assignment operator? If so, why did you declare it const then?
In other words, provide a more meaningful description of the problems you are running into. The one you provided so far is self-contradictory in the most obvious manner.
As AndreyT pointed out, under these circumstances assignment (mostly) doesn't make a lot of sense. The problem is that vector (for one example) is kind of an exception to that rule.
Logically, you copy an object into the vector, and sometime later you get back another copy of the original object. From a purely logical viewpoint, there's no assignment involved. The problem is that vector requires that the object be assignable anyway (actually, all C++ containers do). It's basically making an implementation detail (that somewhere in its code, it might assign the objects instead of copying them) part of the interface.
There is no simple cure for this. Even defining your own assignment operator and using const_cast doesn't really fix the problem. It's perfectly safe to use const_cast when you get a const pointer or reference to an object that you know isn't actually defined to be const. In this case, however, the variable itself is defined to be const -- attempting to cast away the constness and assign to it gives undefined behavior. In reality, it'll almost always work anyway (as long as it's not static const with an initializer that's known at compile time), but there's no guarantee of it.
C++ 11 and newer add a few new twists to this situation. In particular, objects no longer need to be assignable to be stored in a vector (or other collections). It's sufficient that they be movable. That doesn't help in this particular case (it's no easier to move a const object than it is to assign it) but does make life substantially easier in some other cases (i.e., there are certainly types that are movable but not assignable/copyable).
In this case, you could use a move rather than a copy by adding a level of indirection. If your create an "outer" and an "inner" object, with the const member in the inner object, and the outer object just containing a pointer to the inner:
struct outer {
struct inner {
const double coeff;
};
inner *i;
};
...then when we create an instance of outer, we define an inner object to hold the const data. When we need to do an assignment, we do a typical move assignment: copy the pointer from the old object to the new one, and (probably) set the pointer in the old object to a nullptr, so when it's destroyed, it won't try to destroy the inner object.
If you wanted to badly enough, you could use (sort of) the same technique in older versions of C++. You'd still use the outer/inner classes, but each assignment would allocate a whole new inner object, or you'd use something like a shared_ptr to let the outer instances share access to a single inner object, and clean it up when the last outer object is destroyed.
It doesn't make any real difference, but at least for the assignment used in managing a vector, you'd only have two references to an inner while the vector was resizing itself (resizing is why a vector requires assignable to start with).
I very rarely use them - the hassle is too great. Of course I always strive for const correctness when it comes to member functions, parameters or return types.
Errors at compile time are painful, but errors at runtime are deadly. Constructions using const might be a hassle to code, but it might help you find bugs before you implement them. I use consts whenever possible.
I try my best to follow the advice of using const whenever possible, however I agree that when it comes to class members, const is a big hassle.
I have found that I am very careful with const-correctness when it comes to parameters, but not as much with class members. Indeed, when I make class members const and it results in an error (due to using STL containers), the first thing I do is remove the const.
I'm wondering about your case... Everything below is but supposition because you did not provide the example code describing your problem, so...
The cause
I guess you have something like:
struct MyValue
{
int i ;
const int k ;
} ;
IIRC, the default assignment operator will do a member-by-member assignment, which is akin to :
MyValue & operator = (const MyValue & rhs)
{
this->i = rhs.i ;
this->k = rhs.k ; // THIS WON'T WORK BECAUSE K IS CONST
return *this ;
} ;
Thus, this won't get generated.
So, your problem is that without this assignment operator, the STL containers won't accept your object.
As far I as see it:
The compiler is right to not generate this operator =
You should provide your own, because only you know exactly what you want
You solution
I'm afraid to understand what do you mean by const_cast.
My own solution to your problem would be to write the following user defined operator :
MyValue & operator = (const MyValue & rhs)
{
this->i = rhs.i ;
// DON'T COPY K. K IS CONST, SO IT SHOULD NO BE MODIFIED.
return *this ;
} ;
This way, if you'll have:
MyValue a = { 1, 2 }, b = {10, 20} ;
a = b ; // a is now { 10, 2 }
As far as I see it, it is coherent. But I guess, reading the const_cast solution, that you want to have something more like:
MyValue a = { 1, 2 }, b = {10, 20} ;
a = b ; // a is now { 10, 20 } : K WAS COPIED
Which means the following code for operator =:
MyValue & operator = (const MyValue & rhs)
{
this->i = rhs.i ;
const_cast<int &>(this->k) = rhs.k ;
return *this ;
} ;
But, then, you wrote in your question:
I would like to make anything which doesn't change during the objects lifetime const
With what I supposed is your own const_cast solution, k changed during the object lifetime, which means that you contradict yourself because you need a member variable that doesn't change during the object lifetime unless you want it to change!
The solution
Accept the fact your member variable will change during the lifetime of its owner object, and remove the const.
you can store shared_ptr to your const objects in STL containers if you'd like to retain const members.
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <vector>
class Fruit : boost::noncopyable
{
public:
Fruit(
const std::string& name
) :
_name( name )
{
}
void eat() const { std::cout << "eating " << _name << std::endl; }
private:
const std::string _name;
};
int
main()
{
typedef boost::shared_ptr<const Fruit> FruitPtr;
typedef std::vector<FruitPtr> FruitVector;
FruitVector fruits;
fruits.push_back( boost::make_shared<Fruit>("apple") );
fruits.push_back( boost::make_shared<Fruit>("banana") );
fruits.push_back( boost::make_shared<Fruit>("orange") );
fruits.push_back( boost::make_shared<Fruit>("pear") );
BOOST_FOREACH( const FruitPtr& fruit, fruits ) {
fruit->eat();
}
return 0;
}
though, as others have pointed out it's somewhat of a hassle and often easier in my opinion to remove the const qualified members if you desire the compiler generated copy constructor.
I only use const on reference or pointer class members. I use it to indicate that the target of the reference or pointer should not be changed. Using it on other kinds of class members is a big hassle as you found out.
The best places to use const is in function parameters, pointers and references of all kinds, constant integers and temporary convenience values.
An example of a temporary convenience variable would be:
char buf[256];
char * const buf_end = buf + sizeof(buf);
fill_buf(buf, buf_end);
const size_t len = strlen(buf);
That buf_end pointer should never point anywhere else so making it const is a good idea. The same idea with len. If the string inside buf never changes in the rest of the function then its len should not change either. If I could, I would even change buf to const after calling fill_buf, but C/C++ does not let you do that.
The point is that the poster wants const protection within his implementation but still wants the object assignable. The language does not support such semantics conveniently as constness of the member resides at the same logical level and is tightly coupled with assignability.
However, the pImpl idiom with a reference counted implementation or smart pointer will do exactly what the poster wants as assignability is then moved out of the implementation and up a level to the higher level object. The implementation object is only constructed/destructed whence assignment is never needed at the lower level.
I think your statement
If a class has const any member, the
compiler generated assignment operator
is disabled.
Might be incorrect. I have classes that have const method
bool is_error(void) const;
....
virtual std::string info(void) const;
....
that are also used with STLs. So perhaps your observation is compiler dependent or only applicable to the member variables?
I would only use const member iff the class itself is non-copyable. I have many classes that I declare with boost::noncopyable
class Foo : public boost::noncopyable {
const int x;
const int y;
}
However if you want to be very sneaky and cause yourself lots of potential
problems you can effect a copy construct without an assignment but you have to
be a bit careful.
#include <new>
#include <iostream>
struct Foo {
Foo(int x):x(x){}
const int x;
friend std::ostream & operator << (std::ostream & os, Foo const & f ){
os << f.x;
return os;
}
};
int main(int, char * a[]){
Foo foo(1);
Foo bar(2);
std::cout << foo << std::endl;
std::cout << bar<< std::endl;
new(&bar)Foo(foo);
std::cout << foo << std::endl;
std::cout << bar << std::endl;
}
outputs
1
2
1
1
foo has been copied to bar using the placement new operator.
It isn't too hard. You shouldn't have any trouble making your own assignment operator. The const bits don't need to be assigned (as they're const).
Update
There is some misunderstanding about what const means. It means that it will not change, ever.
If an assignment is supposed to change it, then it isn't const.
If you just want to prevent others changing it, make it private and don't provide an update method.
End Update
class CTheta
{
public:
CTheta(int nVal)
: m_nVal(nVal), m_pi(3.142)
{
}
double GetPi() const { return m_pi; }
int GetVal() const { return m_nVal; }
CTheta &operator =(const CTheta &x)
{
if (this != &x)
{
m_nVal = x.GetVal();
}
return *this;
}
private:
int m_nVal;
const double m_pi;
};
bool operator < (const CTheta &lhs, const CTheta &rhs)
{
return lhs.GetVal() < rhs.GetVal();
}
int main()
{
std::vector<CTheta> v;
const size_t nMax(12);
for (size_t i=0; i<nMax; i++)
{
v.push_back(CTheta(::rand()));
}
std::sort(v.begin(), v.end());
std::vector<CTheta>::const_iterator itr;
for (itr=v.begin(); itr!=v.end(); ++itr)
{
std::cout << itr->GetVal() << " " << itr->GetPi() << std::endl;
}
return 0;
}
Philosophically speaking, it looks as safety-performance tradeoff. Const used for safety. As I understand, containers use assignment to reuse memory, i.e. for sake of performance. They would may use explicit destruction and placement new instead (and logicaly it is more correct), but assignment has a chance to be more efficient. I suppose, it is logically redundant requirement "to be assignable" (copy constructable is enough), but stl containers want to be faster and simpler.
Of course, it is possible to implement assignment as explicit destruction+placement new to avoid const_cast hack
Rather than declaring the data-member const, you can make the public surface of the class const, apart from the implicitly defined parts that make it (semi)regular.
class Multiply {
public:
Multiply(double coef) : coef(coef) {}
double operator()(double x) const {
return coef*x;
}
private:
double coef;
};
You basically never want to put a const member variable in a class. (Ditto with using references as members of a class.)
Constness is really intended for your program's control flow -- to prevent mutating objects at the wrong times in your code. So don't declare const member variables in your class's definition, rather make it all or nothing when you declare instances of the class.