C++ attempting to reference a deleted function - c++

I am trying to temporary store a vector of unique pointers and switch them between 2 objects. Here I try to move the ownership of the vector to a temporary vector named oldcards.
std::vector<std::unique_ptr<Building>> oldCards = std::move(player.getBuildingCards());
player.setBuildingCards(std::move(otherPlayer.getBuildingCards()));
otherPlayer.setBuildingCards(std::move(oldCards));
Player.cpp
std::vector<std::unique_ptr<Building>> const& Player::getBuildingCards() const
{
return this->buildingCards;
}
void Player::setBuildingCards(std::vector<std::unique_ptr<Building>> buildingCards)
{
this->buildingCards = std::move(buildingCards);
}
Player.h
std::vector<std::unique_ptr<Building>> buildingCards;
To conclude: I want to swap 2 vectors, I want player to have the ownership of the vector of otherPlayer and vice versa. However, I get the: attempting to reference a deleted function error. How can I achieve this?

I am trying to temporary store a vector of unique pointers and switch them between 2 objects.
Why? Using std::vector::swap would accomplish the same thing with less effort. (Note that this swap most likely should occur within a member function, so there would be no need to use the public accessor functions.)
std::vector<std::unique_ptr<Building>>const& Player::getBuildingCards() const
This returns a const reference. You are not allowed to change something marked const. Moving data out of something counts as changing that something, so moving from getBuildingCards() is not allowed.
void Player::setBuildingCards(std::vector<std::unique_ptr<Building>> buildingCards)
This function takes a copy of a vector as a parameter. Since a vector of unique_ptr cannot be copied, this function signature is DOA. (For the intended purpose, you would want the type of the parameter to be std::vector<std::unique_ptr<Building>>&& to indicate that you will be moving from the parameter.)

You cannot move from cons T& so copy constructor of oldCards is called which is of course deleted. player.getBuildingCards() cannot change the player instance anyway because you marked it as const.
Cleanest solution (at least according to me) would to implement swapBuildingCards friend function:
class Player
{
//...
std::vector<std::unique_ptr<Building>> buildingCards;
friend static void swapBuildingCards(Player& p1, Player &p2)
{
using std::swap;
swap(p1.buildingCards,p2.buildingCards);
}
};

Related

error when adding into vector of pointers

class A{
Add(const B&);
vector <B*> vect;
};
A & A::Add(const B& obj){
vect.push_back(&obj);
return *this;
}
here I am getting fpermissive error, because argument of push_back is constant, how do I get rid of this?
I tried to create local copy in Add such as
B tmp;
tmp = obj;
vect.push_back(&tmp);
but I am not sure about this, as program step out of this method Add, tmp gets destructed, and adress in vector will point to invalid place in memory?
Your problem arises from API inconsistency. 2 options here:
Drop the const from the signature of Add: Add(B&)
Store const B* pointers in the vector: vector<const B*> vect;
The first option will allow to modify the contents of your objects while the second one will forbid it. The choice depends on your program logic.
Your problem is that if you provide a const reference as the function parameter of Add you are telling the compiler that whatever you are passing is never going to be changed as an effect of that function.
On the other hand you try to store a non-const pointer in the vector which means that the users of that vector are allowed to change the value correlated to that pointer.
To get rid of the error you have to decide what is the type of behaviour you actually want from your program:
if you want to store read-only references to your "B" objects then you have to store them as const pointer in the vector. If you want the users of that vector to be able to use non-const functions of B, that is to change B, you have to pass it to the Add function as non-const reference.

Is it a good practice to make a method which modifies data outside the class const?

I would like to ask a question about methods' const-correctness. Let me illustrate the situation.
class MyClass
{
public:
...
void DiscussedMethod() { otherClass->NonConstMethod(); }
private:
OtherClass *otherClass;
};
I have a class MyClass which keeps a pointer to OtherClass. In DiscussedMethod it calls OtherClass::NonConstMethod which modifies some visible data.
I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)? Would it be a bad practice? Or is both fine?
What if the OtherClass kept a pointer to the MyClass and in NonConstMethod modified some of the MyClass' data (meaning that the MyClass member data would change during the DiscussedMethod call). Would it be a bad practice to make the DiscussedMethod const then?
As far as I've been able to find out, the const on a method is mostly a code documenting thing, so I would probably lean toward to not making the DiscussedMethod const, but I would like to hear your opinions.
EDIT: Some replies take the into account whether the object pointed to by otherClass is owned by the MyClass object. This is not the case in the scenario I'm working with. Lets say that both objects exist independently side by side (with the ability to modify each other). I think this analogy describes my situation quite well.
For example consider something like doubly-linked list, where each element is a class that keeps pointer to its neighbours and member variable color. And it has method MakeNeighboursRed which changes the color of its neighbours but doesn't affect the calling object's state itself. Should I consider making this method const?
And what if there was some possibility that MakeNeighboursRed would call neighbour's MakeNeighboursRed. So in the end the state of the object for which MakeNeighboursRed has been called originally would change as well.
And I would like to thank you all for your opinions :-)
If MyClass owns the OtherClass instance i wouldn't make DiscussedMethod constant.
The same goes for classes, managing resources. I.e. the standard containers do not return non const references or pointers to the managed memory using const functions, although it would be "possible" (since the actual pointer holding the resource is not modified).
Consider
class MyClass
{
public:
bool a() const { return otherClass->SomeMethod(); }
void b() const { otherClass->NonConstMethod(); }
private:
OtherClass *otherClass;
};
void foo (MyClass const &x)
{
cout << boolalpha << x.a() << endl;
x.b(); // possible if b is a const function
cout << boolalpha << x.a() << endl;
}
The foo could print two different values although an implementor of foo would probably expect that two function calls on a const object will have the same behaviour.
For clarification:
The following is invalid according to the standard since the const version of operator[] returns std::vector<T>::const_reference which is a constant reference to the value type.
std::vector<int> const a = { /* ... */ };
a[0] = 23; // impossible, the content is part of the state of a
It would be possible if there was only one signature of this function, namely referece operator[] (size_t i) const;, since the operation does not alter the internal pointers of the vector but the memory they point to.
But the memory, managed by the vector is considered to be part of the vectors state and thus modification is impossible through the const vector interface.
If the vector contains pointers, those pointer will still be unmodifiable through the public const vector interface, although the pointers stored in the vector may well be non const and it may well be possible to alter the memory they point to.
std::vector<int*> const b = { /* ... */ };
int x(2);
b[0] = &x; // impossible, b is const
*b[0] = x; // possible since value_type is int* not int const *
In OOP object should be fully described by its state, available through its interface. Thus, const methods should not alter object's state, if these changes might be observed through the interface.
A good example is a mutable mutex inside your class to guard some shared resources. It might be modified from const method, since it does not introduce any changes observable via class interface.
General rule of thumb is, that if you can make a member function const, you probably should. The reason for that is that it allows you to catch unintended behaviour and bug easier.
Another argument in favor would be that if you have this function as const you are allowed to call it on const object, so it isn't really a documentation thing.
Overall it depends what the other class is. It's not black and white...
If otherClass is a log object (for example) and you want to log the operation of the current object then it's perfectly fine calling it from a const function.
If the otherClass is a container that for design (or implementation) purposes is implemented as a separate object than effectively a const function modifies the object making this a very bad idea.
I hope this helps.
It's totaly incorrect to make DiscussedMethod const as it changes it's *this state. The only loophole to this is making non-logically-part-of-object's-state member data mutable so they can be changed in const functions. This would be things like a member that hold a count for "number of times function x() has been called". Any thing else is part of the object's state, and if a function changes it (at any level), that function isn't const.
I would like to know, whether it would be a good practice to make the DiscussedMethod const (since it doesn't modify any member data)?
otherClass is member data, and it (or rather, the object it points to) gets modified.
Consider the semantics should the pointer to otherClass be refactored to a fully-owned object... whether something is held as a pointer, reference, or object doesn't change the semantical ownership, IMO.

Class Member Variable not Saving State

I'm new to C/C++, so people excuse me if this is a noob question.
I have a controller class, which has a private member variable which is a vector<Contact> contacts. The class has methods which allow us to change the state of this vector (standard CRUD operations).
The class has a public method called get_contacts() which returns this private vector of objects:
std::vector<Contact> Contacts_Controller::get_contacts() const {
return this->contacts;
}
I have a method which adds the contact to this private vector via push_back(). The issue is that if the add_contact() method uses the accessor method, then the class variable does not get updated:
void Contacts_Controller::add_contact(const Contact &contact) {
this->get_contacts().push_back(contact);
}
I assume this is a memory issue, perhaps I have some issues with my use of const or I'm not correctly using references, because the following code works exactly as expected:
void Contacts_Controller::add_contact(const Contact &contact) {
this->contacts.push_back(contact);
}
Using either method won't return any errors, but if I then request the vector of contacts after using the first method it'll be empty, whereas the second method correctly adds data to the vector.
Again, sorry if this is a noob question, but I'm completely stumped, and I wouldn't know what to search for! How would I fix this referencing issue?
"The class has a public method called get_contacts() which returns this private vector of objects"
Nope, it returns a copy. You need to return by reference to get the actual member:
std::vector<Contact>& Contacts_Controller::get_contacts(){
return this->contacts;
}
Note that I removed the const, otherwise you'd have to mark the return as const also and you wouldn't be able to modify it.
The issue is that your function is returning the vector by value, which means the calling function gets a copy.
When you call push_back() on it, only the copy gets the extra member.
Your function could return a reference. Then your user can call push_back(). If it is a member variable of your class and you are returning a non-const reference (which you must to allow the modification) your function will probably also be non-const.
Thus:
std::vector<Contact> & Contacts_Controller::get_contacts() // not const
{ return this->contacts; }
You can also have a read-only version, as an overload.
std::vector<Contact> const & Contacts_Controller::get_contacts() const
{ return this->contacts; }
This version allows read-only access to the contacts and can also be a const member function.
When you call get_contacts, you return a copy of this->contacts. If you want to share a vector, either return a reference to it (but you must be sure that your reference will stay valid so your class instance won't be moved or copied), or use a smart pointer to dynamically allocate the space for your vector and extend its lifetime until the last reference to it has been destructed. In this case use a member with type std::shared_ptr<std::vector<Contact> >

Delete custom object from vector

I have the following code to store objects of type LVA in a vector.
I've implemented a method for adding a LVA Object to the vector.
First question: Is it okay if i use a reference to the LVA object in this method?
Now i want to implement a method for the deletion of a LVA object. I want to have the following method signature: void RemoveLVA(LVA& lva). How can I implement this method? i.e. How can i find the right object in the vector to delete it?
Manager.h
class Manager {
public:
Manager();
Manager(const Manager& orig);
virtual ~Manager();
vector<LVA> GetLvas() const;
void AddLva(LVA& lva);
private:
vector<LVA> lvas;
};
Manager.cpp:
#include "Manager.h"
Manager::Manager() {
}
Manager::Manager(const Manager& orig) {
}
Manager::~Manager() {
}
vector<LVA> Manager::GetLvas() const {
return lvas;
}
void Manager::AddLva(LVA& lva) {
lvas.push_back(lva);
}
Is it okay if i use a reference to the LVA object in AddLva(LVA& lva)?
Yes, std::vector will have a copy of your original object after push_back() is complete.
How can I implement RemoveLVA(LVA& lva)?
You will need to find the object in your vector. (You may use std::find() if operator==() is defined for LVA.) Then invoke the erase() function for your vector.
Is it okay if i use a reference to the LVA object in this method?
No problem. You are actually doing a copy by a push_back operation.
Without knowing more about LVA, it's hard to be precise, but
you probably want a const reference for AddLva, since you're
not modifying it in the function (and you may want to pass
a temporary).
For removal: you'll have to define some sort of
equivalence function over LVA is you want to remove a matching
element. This can be LVA::operator==, or some other object or
function: in the first case, you use std::find to find the
position, and in the second, std::find_if. If the vector can contain
more than one matching element, you might want to look into std::remove or std::remove_if.
Your insertion method is right, but don't forget that only a copy from your LVA object is inserted in the vector. it means than in the RemoveLVA method, you will need to use somthing like an operator== overload to std::find the vector's object which matches your parameter, and then deleting it.
You may prefer to insert pointers or std::shared_ptr of LVA in your vector. No object copy will then occur, and the search of an object will fall back to a comparison of pointer, given you keep the pointer somewhere else in your program (2 objects with same contents and different stack or heap locations would then compare to false).
Yes, AddLva can take a reference, although it would typically take a const reference:
void Manager::AddLva(const LVA& lva) {
lvas.push_back(lva);
}
Note however that if you are expecting that the reference is added to the vector, this isn't doing that. A copy of the object lva refers to is made, and that copy is added to the vector.
Yes it's Ok to pass the LVA object as ref in your add and remove method. You could also declare those parameters as 'const' because I suppose add and remove will not affect the object .
for the remove method
void RemoveLVA(const LVA& lva)
{
std::vector<LVA>::iterator position =
std::find(lvas.begin(), lvas.end(), lva);
if (position != lvas.end())
{
lvas.erase(position);
}
}
but LVA class must have an == operator.
good luck.

How are objects passed to functions C++, by value or by reference?

Coming from C#, where class instances are passed by reference (that is, a copy of the reference is passed when you call a function, instead of a copy of the value), I'd like to know how this works in C++. In the following case, _poly = poly, is it copying the value of poly to _poly, or what?
#include <vector>
using namespace std;
class polynomial {
vector<int> _poly;
public:
void Set(vector<int> poly);
};
void polynomial::Set(vector<int> poly) {
_poly = poly; <----------------
}
poly's values will be copied into _poly -- but you will have made an extra copy in the process. A better way to do it is to pass by const reference:
void polynomial::Set(const vector<int>& poly) {
_poly = poly;
}
EDIT I mentioned in comments about copy-and-swap. Another way to implement what you want is
void polynomial::Set(vector<int> poly) {
_poly.swap(poly);
}
This gives you the additional benefit of having the strong exception guarantee instead of the basic guarantee. In some cases the code might be faster, too, but I see this as more of a bonus. The only thing is that this code might be called "harder to read", since one has to realize that there's an implicit copy.
This will do a shallow-copy of the vector of ints. This will generally work as you would expect (_poly will end up containing the same values as poly).
You would see some strange behaivor if you had pointers (as they would be copied by value).
In general, you would want to pass that parameter by const reference:
void polynomial::Set( const vector<int>& poly )
In this case, passing by const reference will not affect the outcome and will be more efficient since it will eliminate an unneeded copy of the vector being passed into the method.
This will copy the entire vector. Assignment is by value in C++. If you are assigning a pointer, the pointer value is assigned. References may not be reassigned to refer to another object once initialized, so assignment of them alters the referent object.
The copy operator for vectors will copy the contents of the vector over.
There are three possibilities:
Pass by value
void someFunction(SomeClass theObject);
Pass a pointer
void someFunction(SomeClass *theObject);
Pass by reference
void someFunction(SomeClass &theObject);
Your vector will be copied.
What's actually going on is that the "=" operator of vector has been overloaded to do the actual copy.
Yes, the line you point to is copying the entire vector. Furthermore, there will be a copy on the function call, as well, since that's not const.
Basically, if the vector has any size to it, this is VERY expensive.
Unless you assign or pass a parameter by reference (using the & prefix) you are passing by value. For classes, this means that a copy of the object is constructed using either a supplied or implicitly generated (shallow) copy constructor for the type. This can be expensive - and is often undesirable.
In your example, the vector is copied twice - once when it is passed as a parameter to the Set() method, and again when it is assigned to the _poly member.
You could avoid the first copy by passing the vector by reference:
void polynomial::Set(const vector<int>& poly) // passes the original parameter by reference
{
_poly = poly; // still makes a copy
}