Copy contents of a unique pointer array in the copy constructor - c++

My class contains a unique pointer to an array. When the copy constructor is called, I want the class to create its own unique pointer array and just copy the contents of the old unique pointer array. I keep getting errors about converting from a const value, and I'm not sure how to get around it.
My pointer is declared under private like this:
std::unique_ptr<Manager[]> managers;
I planned to just loop through the array and copy manually, so I made this copy constructor:
Restaurant::Restaurant(const Restaurant &_r)
{
Manager *_managers = _r.managers;
for (int i = 0; i < MAX_MANAGERS; i++)
{
managers.get()[i] = _managers[i];
}
}
It gives the const convert error on this line:
Manager *_managers = _r.managers;
I just want to make a deep copy. How can I go about it to make this work?

The reason that it won't compile is that
_r.managers is of type std::unique_ptr<Manager[]>, but you want to initialize a raw pointer with this.
just change it to:
Restaurant::Restaurant(const Restaurant &_r)
{
for (int i = 0; i < MAX_MANAGERS; i++)
{
managers.get()[i] = _r.managers.get()[i];
}
}
or first take a smart pointer's data (which is an array)
Manager *_managers = _r.managers.get();
and then you can use it as was before:
for (int i = 0; i < MAX_MANAGERS; i++) {
managers.get()[i] = _managers[i];
}

In the line giving you an error, managers is an std::unique_ptr<Manager[]>. You're trying to assign it to a Manager*, which won't work.
You can fix it by taking the raw pointer of of the unique_ptr, for example:
Manager *_managers = _r.managers.get();

In order to copy the content of unique_ptr<>, you might want to use "deep copy", this means that you write copy constructor in class Manager and a clone function.
Example for copy constructor:
Manager(Manager const& manager) {
name = manager.name;
title = manager.title;
}
clone function:
unique_ptr<Manager> clone() const {
return make_unique<Manager>(*this);
}

Related

How to delete class as this and set it as null in c++

So, I have an array of a class called "Customer"
Customer** customersarray[] = new Customer*[customer];
I'm receiving int customer with cin.
anyways, in customer.cpp, there is a method called void deactivate().
which goes like this:
void Custmoer::deactivate()
{
if (this != NULL)
remove this;
//this = NULL; I want to do this but it doesn't work.
}
and the purpose of this is to remove it from customer array when satisfies a certain condition. So for example,
for (int i = customer - 1; i >= 0; i--)
{
if (customersarray[i]->getAngerLevel() == 5) {
customersarray[i]->deactivate();
}
for (int z = i; i < customer - 1; i++) {
*(customersarray + z) = *(customersarray + z + 1);
}
customer--;
}
so my first questions are:
why does this = NULL not work?
is there a simpler way to remove something from pointer array when a condition is satisfied? (for example, remove all customers that has anger level of 5.)
Your mistake is thinking that you can remove something from a Customer* array by some magic inside the Customer class, but that's not true. Just remove a customer from the customer array where ever the customer array is. For instance using remove_if
#include <algorithm>
Customer** customersarray = new Customer*[customer];
...
customer = std::remove_if(customersarray, customersarray + customer,
[](Customer* c) { return c->anger() == 5; }) - customersarray;
This updates the customer variable to be the new size of the array, but doesn't free or reallocate any memory. Since you are using dynamic arrays and pointers you are responsible for that.
Which is why you should really not be using pointers or arrays, but using vectors instead.
std::vector<Customer> customerVector;
Life will be so much simpler.
Type of "this" is a constant pointer which means you cant change where it points
Your function can return a boolean and if its true just set your pointer to null
You'll be much better off using a std::vector, all memory memory management gets much safer. You cannot modify the this pointer, but that would be meaningless anyway:
It is a local variable, so any other pointer outside would not be changed, not even the one you called the function on (x->f(): the value of x is copied into this).
It contains the address of the current object - the current object is at a specific memory location and cannot be moved away from (not to be mixed up with 'moving' in the context of move semantics!).
You can, however, delete the current object (but I don't say you should!!!):
class Customer
{
static std::vector<Customer*> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
delete this;
}
}
Might look strange, but is legal. But it is dangerous as well. You need to be absolutely sure that you do not use the this pointer or any other poiner to the current object any more afterwards (accessing non-static members, calling non-static functions, etc), it would be undefined behaviour!
x->commitSuicide();
x->someFunction(); // invalid, undefined behaviour!!! (x is not alive any more)
Similar scenario:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
{
customers.erase(i); // even now, this is deleted!!! (smart pointer!)
this->someFunction(); // UNDEFINED BEHAVIOUR!
}
}
}
If handling it correctly, it works, sure. Your scenario might allow a much safer pattern, though:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
Customer()
{
customers->push_back(this);
};
~Customer()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
}
}
There are numerous variations possible (some including smart pointers); which one is most appropriate depends on the use case, though...
First of all, attending to RAII idiom, you are trying to delete an object before using its destructor ~Customer(). You should try to improve the design of your Customer class through a smart use of constructor and destructor:
Customer() {// initialize resources}
~Customer() {// 'delete' resources previously created with 'new'}
void deactivate() {// other internal operations to be done before removing a customer}
Then, your constructor Customer() would initialize your internal class members and the destructor ~Customer() would release them if necessary, avoiding memory leaks.
The other question is, why do you not use another type of Standard Container as std::list<Customer>? It supports constant time removal of elements at any position:
std::list<Customer> customers
...
customers.remove_if([](Customer foo) { return foo.getAngerLevel() == 5; });
If you only expect to erase Customer instances once during the lifetime of the program the idea of using a std::vector<Customer> is also correct.

Object going out of scope / transferring ownership

I have an issue with creating objects, adding them to a container class, and having them go out of scope in C++.
As an example, my main.cpp
Container container;
for (unsigned int i = 0; i < 10; i++) {
Item item;
container.add_item(item);
}
and the interface of container.h
struct Container {
std::vector<std::reference_wrapper<Item>> items;
void add_item(Item& item); // Push back of items vector.
};
and item.h
struct Item {
std::unique_ptr<AnotherThing> unrelated_thing;
};
The problem is later on in my main class, the Containers created inside the for-loop have gone out of scope. If I change add_item to pass by value, it gives me issues with the unique_ptr and copy constructor.
Is there some idiomatic way to create objects inside a scope and "transfer" them to another class?
If I change add_item to pass by value, it gives me issues with the unique_ptr and copy constructor.
Your vector need to hold objects by value:
std::vector<Item> items;
then you need to move your object into vector when passed by value:
void Container::add_item( Item item )
{
items.push_back( std::move( item ) );
}
and then you need to move your object in the loop as well:
for (unsigned int i = 0; i < 10; i++) {
Item item;
container.add_item( std::move(item) );
}
or you can simply pass temporary:
for (unsigned int i = 0; i < 10; i++) {
container.add_item( Item() );
}
There are a few ways to handle this. This is basically the exact use-case for passing xvalues. Passing by value will cause a copy of all members of item. If there are members that could have large amounts of data allocated on the heap, such as a std::vector, you will want to avoid this copy and allocation by moving your members.
The simple answer is to pass by what Scott Meyers calls a 'Universal Reference'
void Container::add_item( Item&& item) {
items.push_back( std::move(item))
}

Order of destructors

I have these kind of classes:
Game:
class Game {
private:
BoardField*** m_board_fields;
public:
Game() {
m_board_fields = new BoardField**[8];
for (int i = 0; i < 8; i++) {
m_board_fields[i] = new BoardField*[8];
}
}
Game::~Game() {
for (int i = 0; i < 8; i++) {
for (int j = 0; i < 8; j++) {
delete m_board_fields[i][j];
}
delete[] m_board_fields[i];
}
delete[] m_board_fields;
}
}
BoardField:
class BoardField {
private:
ChessPiece* m_piece;
....
public:
BoardField::~BoardField() {
delete m_piece;
}
}
And on the close of the program I get error in ~BordField:
Exception thrown: read access violation.
this was 0xFDFDFDFD.
Did I made my destructors incorrect? What is the best way to clear memory from multidimensional array ?
There is are two fundamental flaws in your design:
there is no clear ownership of the BoardFields: someone create it, someone else deletes it. It can work if you're very cautious but it's error prone.
you do not ensure the rule of 3 (or better 5): if you have any piece of code where you create a copy of either your Game or a of any BoardField the first object that gets destroyed will delete the m_piece pointer, and when the second object gets destroyed, it'll try to delete a second time the same pointer, which is UB.
There is a third important issue: you're over-using raw pointers:
if m_board_fields is a 2d array of fixed size, make it a fixed size array (aka BoardField* m_board_fields[8][8]). If you want to keep its size dynamic, use vectors.
a cell of m_board_field could be a pointer if there's some polymorphism expected. But this seems not the case here, as obviously ChessPiece is the polymorphic class. So better use plain fields instead of pointers (aka BoardField m_board_fields[8][8]).
Finally, instead of using raw pointer to ChessPiece, better use a shared_ptr<ChessPiece> : you don't have to worry about shallow pointer copies and double delete; the shared_ptr will take care of itself and destroy the object if it's no longer used.

Copying an array from a struct which is senŠµ through a function

I have want to send a struct to json->setInformation but my program crashes when i try to copy the array which is inside the struct. The rest of the data is okay its just the array which makes the crash occur.
info = data->getInformation();
json->setInformation(info);
getInformation returns a struct which i can read in main.cpp
when i try to send this struct to setInformation it crashes...
information.h which holds my struct
struct information{
String location;
String protocol;
uint8_t groupID;
uint8_t* data;
information& operator=(const struct information& that){
location = that.location;
protocol = that.protocol;
groupID = that.groupID;
for (int i = 0; i < 9; ++i){
data[i] = that.data[i];
}
return *this;
}
};
json.cpp
void JSON::setInformation(information data){
info->location = data.location;
info->protocol = data.protocol;
info->groupID = data.groupID;
// for (int i = 0; i < 9; ++i){
// info->data[i] = data.data[i];
// }
// Serial.print("after JSON: ");
// Serial.println(info->data[0]);
}
this code works fine but when i uncomment the for lop which should copy the array it crashes
Did you allocate memory for your uint8_t data* parameter before using it ?
Then remember to deallocate memory when you don't need it anymore, thus avoiding memory leaks.
Your object is passed by copy to the function, but you have no copy constructor.
Default copy constructor will not copy you raw pointer correctly. So either you declare and implement a copy constructor, either you replace your raw pointer (uint8_t*) by a vector (std::vector<uint8_t>) which is safely copyiable (then copying the object will become a valid operation).
Moreover, we can't see who's allocating/deallocating your raw pointer, but I suspect you are missing a destructor function too.
Your code breaks the rule of three which is the minimal requirement for any class you'll declare in C++.

Copy consutrctor w/ multiple pointers

I am trying to create a copy constructor for a class with pointer variables. Something is going wrong with the copy construction though, as I segfault when I try to access pointers in my new object...
/* Copy Constructor */
Solver::Solver(const
Solver &obj)
{
// Pointers to use in modified-Midpoint method.
double *m_yTemp1 = new double[CONST_numVariables];
double *m_yTemp2 = new double[CONST_numVariables];
double *m_dTemp = new double[CONST_numVariables];
// Triple pointer to store tableau of data for extrapolation.
double ***m_extrapTableau = new double**[CONST_maxDiv];
*m_extrapTableau = *obj.m_extrapTableau;
for(int i=0; i<CONST_maxDiv; i++)
{
m_extrapTableau[i] = new double*[i+1];
*m_extrapTableau[i] = *obj.m_extrapTableau[i];
for(int j=0; j<=i; j++)
{
m_extrapTableau[i][j] = new double[CONST_numVariables];
*m_extrapTableau[i][j] = *obj.m_extrapTableau[i][j];
}
}
// Pointer of step sizes for extrapolation of modified-Midpoint.
double *CONST_extrap = new double[CONST_maxDiv];
for(int i=0; i<CONST_maxDiv; i++)
{
CONST_extrap[i] = 2.*(i+1.);
}
// Change pointer of new object from already used memory to newly allocated.
*m_yTemp1 = *obj.m_yTemp1;
*m_yTemp2 = *obj.m_yTemp2;
*m_dTemp = *obj.m_dTemp;
*CONST_extrap = *obj.CONST_extrap;
}
My initial questions are:
If I have other non-pointer variables in the class, are they automatically copied or do I need to specify them as well?
How do I deal with passing the address of double or triple pointers? I think I may be doing this wrong.
If CONST_numVariables and CONST_maxDiv are constants set in the class, can they be used in this copy constructor, assuming that they have been set when I copy an object?
The problem with your segfault is here:
double ***m_extrapTableau = new double**[CONST_maxDiv]; // (1)
*m_extrapTableau = *obj.m_extrapTableau; // (2)
In (1) you DECLARE a variable m_extrapTableau LOCAL to your constructor.
But in (2) I can see that you have a class membber with the same name. So the local m_extrapTableau of your constructor will be properly intialised. But it hides the class member that will remain uninitialized for subsequent uses.
About your remaining questions:
1) if you implement a copy constructor, you have to take care of copying everything you need.
2) passing adress of double or tripple pointers requires you to iterate through each level initializing the pointers correctly before using any element of your table. You should consider using vectors of vectors or vectors of vectors of vectors. These a much more easy to initialise, copy, etc...
3) if they are const and you didn't initialize them to another value with a brace initializer they should be usable as such.