Move constructor c++ - c++

What's the right way to do a move constructor ?
class A{
...some stuff...
private:
int i;
std::string str;
};
A::A(A &&a)
{
*this = std::move(a);
};
or
A::A(A &&a)
{
this->str = std::move(a.str);
};
In the second case, is it useful to std::move() the int value ?

It should be
A::A(A&& other)
: i{other.i},
str{std::move(other.str)} {
// nop
}
This is the default implementation for a move constructor.

Related

c++ copy assignment operator for reference object variable

I give the following example to illustrate my question:
class Abc
{
public:
int a;
int b;
int c;
};
class Def
{
public:
const Abc& abc_;
Def(const Abc& abc):abc_(abc) { }
Def& operator = (const Def& obj)
{
// this->abc_(obj.abc_);
// this->abc_ = obj.abc_;
}
};
Here I do not know how to define the copy assignment operator. Do you have any ideas? Thanks.
references cannot be assigned to. You need something that can. A pointer would work, but they're very abusable.
How about std::reference_wrapper?
#include <functional>
class Abc
{
public:
int a;
int b;
int c;
};
class Def
{
public:
std::reference_wrapper<const Abc> abc_;
Def(const Abc& abc):abc_(abc) { }
// rule of zero now supplies copy/moves for us
// use the reference
Abc const& get_abc() const {
return abc_.get();
}
};
A reference cannot be assigned. Due to this, one can only define it via placement new and copy construction:
Def& operator = (const Def& obj)
{
this->~Def(); // destroy
new (this) Def(obj); // copy construct in place
}
But it is really unnecesary. Just use a pointer.

inserting object in a map without copying the object

Is it possible to insert objects in a map, if the class of the object has disabled copy constructor and disabled copy operator? Is move semantics useful here?
#include <map>
class T {
public:
T(int v): x(v) {};
private:
T(const T &other); // disabled!
T &operator=(const T &other); // disabled!
int x;
};
int main() {
std::map<int, T> m;
m[42] = T(24); // compilation error here!
}
edit I was not completely clear. The object is huge, so I don't want to make unnecessary copies of it. But I can modify the code of the class (maybe I need to implement move semantics?) and not the user code (the main function in the example).
Use emplacement syntax:
m.emplace(std::piecewise_construct,
std::forward_as_tuple(42), std::forward_as_tuple(24));
// ^^ ^^
// int(42) T(24)
Or, in C++17, use try_emplace:
m.try_emplace(42, 24);
This might be what you are looking for:
class T {
public:
T(){};
T(int v): x(v) {};
T(const T &other) = delete;
T(T&& other) {x = other.x; std::cout << "move ctor\n";}
T &operator=(const T &other) = delete;
T& operator=(T&& other) {x = other.x; std::cout << "move assigment\n";}
private:
int x;
};
int main() {
std::map<int, T> m;
m.insert(std::make_pair(42, T(24)));
m[44] = T(25);
}
You might insert as pointer:
public:
T(int v) : x(v) {};
int getX(){ return this->x; }
private:
T(const T &other); // disabled!
T &operator=(const T &other); // disabled!
int x;
};
int main()
{
std::map<int, T*> m;
m[42] = new T(24); // no compilation error here!
std::cout << m[42]->getX() << std::endl; // prints out 24
return 0;
}

Extending default copy constructor

In a copy constructor of a struct/class, how can I avoid copying all the basic (int, double, etc.) members one by one if the intention is to copy a pointer successfully? Is it possible to extend the default copy constructor in this sense?
struct Type
{
int a;
double b;
bool c;
// ... a lot of basic members
int* p;
Type()
{
p = new int;
*p = 0;
}
Type (const Type& t)
{
// how to avoid copying these members one by one
this.a = t.a;
this.b = t.b;
this.c = t.c;
// but only add this portion
this.p = new int;
*this.p = *t.p;
}
};
Create an RAII wrapper for the int * data member that allows copying/moving.
struct DynInt
{
std::unique_ptr<int> p;
DynInt() : DynInt(0) {}
explicit DynInt(int i) : p(new int(i)) {}
DynInt(DynInt const &other) : p(new int(*other.p)) {}
DynInt& operator=(DynInt const& other)
{
*p = *other.p;
return *this;
}
DynInt(DynInt&&) = default;
DynInt& operator=(DynInt&&) = default;
// maybe define operator* to allow direct access to *p
};
Then declare your class as
struct Type
{
int a;
double b;
bool c;
// ... a lot of basic members
DynInt p;
};
Now, the implicitly generated copy constructor will do the right thing.

Freeing resources in a class with shared pointers

I have a class like the following:
class A {
SuperHugeClass* s;
public:
A(){ s = new SuperHugeClass(); }
};
Because SuperHugeClass takes a lot of memory, I'm fine with the shallow copying provided by the default constructor and assignment operator. However, I also don't want to leak memory, so I need to delete s, but I have to be careful about it because otherwise I'll delete it more than once.
One way of doing this is by refcounting s as follows:
class A {
int* refcount;
SuperHugeClass* s;
public:
A(){
refcount = new int(1);
s = new SuperHugeClass();
}
A(const A& other) : refcount(other.refcount), s(other.s) {
(*refcount)++;
}
~A() {
(*refcount)--;
if (!(*refcount)) {
delete refcount;
delete s;
}
}
friend void swap(const A& a, const A& aa) {
std::swap(a.refcount, aa.refcount);
std::swap(a.s, aa.s);
}
A& operator=(A other) {
swap(*this, other);
return (*this);
}
};
This is the first time I've needed to do something like this, but it seems to me that this should be pretty standard and so there should be a 'canonical' solution. Are there any other ways of doing this? Thanks!
Use std::shared_ptr
class A {
std::shared_ptr<SuperHugeClass> s;
public:
A()
: s(new SuperHugeClass())
{
}
};
and thats it. Default generated copy constructor/assignment operator/destructor do just what you need.
Use std/boost::shared_ptr instead of your ref-counted pointer.

local classes c-ism

Only first pair of values output on running this program seem correct, the others don't. What is going on?
#include <iostream>
#include <vector>
class a
{
public:
class b
{
public:
a* parent;
void test()
{
std::cout<<parent->value<<std::endl;
}
} b1;
unsigned long value;
a()
{
b1.parent = this;
value = 2;
}
void go()
{
value++;
b1.test();
}
};
int main()
{
{
a a1;
a1.go();
std::cout<<a1.value<<std::endl;
}
std::cout<<std::endl;
{
a a1; a1 = a();
a1.go();
std::cout<<a1.value<<std::endl;
}
std::cout<<std::endl;
{
std::vector<a> a1; a1.push_back(a());
a1.at(0).go();
std::cout<<a1.at(0).value<<std::endl;
}
return 0;
}
You are missing a copy ctor and assignment operator for type 'a'. When copying or assigning objects, you consequently don't properly update their b1.parent. Instead, the b1.parent values point to a different 'a' object than their real parent.
To see this problem in action, use this in your existing code:
void go() {
value++;
std::cout << (this == b1.parent ? "as expected\n" : "uh-oh\n");
b1.test();
}
To fix it, modify class a:
a() : b1 (this), value (2) {} // a change from your default ctor
a(a const &x) : b1 (this), value (x.value) {}
a& operator=(a const &x) {
value = x.value;
return *this;
}
And modify class b (necessarily to use the ctor initializer as I do above):
b(a *parent) : parent (parent) {}