How to implement the move function in C++? - c++

I want to know the internals of the move function in C++.
For that, I aim to make my own implementation of the move function called move2.
Here is my implementation with prints to track memory allocation.
#include <iostream>
#include <vector>
using namespace std;
void * operator new(size_t size) {
cout << "New operator overloading " << endl;
void * p = malloc(size);
return p;
}
void operator delete(void * p) {
cout << "Delete operator overloading " << endl;
free(p);
}
template<typename T>
T move2(T& input) {
cout << "Running move2 " << endl;
return (T&&)input;
}
int main()
{
{
cout<<"Test#1"<<endl;
vector<int> temp1(10,4);
vector<int> temp2 = temp1;
}
{
cout<<"Test#2"<<endl;
vector<int> temp3(10,4);
vector<int> temp4 = (vector<int>&&)(temp3);
}
{
cout<<"Test#3"<<endl;
vector<int> temp5(10,4);
vector<int> temp6 = move(temp5);
}
{
cout<<"Test#4"<<endl;
vector<int> temp7(10,4);
vector<int> temp8 = move2(temp7);
}
return 0;
}
Here is the output
Test#1
New operator overloading
New operator overloading
Delete operator overloading
Delete operator overloading
Test#2
New operator overloading
Delete operator overloading
Test#3
New operator overloading
Delete operator overloading
Test#4
New operator overloading
Running move2
Delete operator overloading
I want to know if my implementation of move2 is correct and can I use it in production?
Update:
I found the GCC implementation of move
/**
* #brief Convert a value to an rvalue.
* #param __t A thing of arbitrary type.
* #return The parameter cast to an rvalue-reference to allow moving it.
*/
template<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }

std::move() takes in a forwarding reference, and returns a T&& rvalue reference. Your move2() does neither. It takes in an lvalue reference, and returns a T by value.
Your code "works" due to copy elision avoiding a temporary object being created when your function returns a new object by value, thus allowing temp8 to be constructed directly with your type-casted reference to input, thus transferring ownership of its data. That is not because of a proper move2() implementation, though.
Try this instead:
template<typename T>
std::remove_reference_t<T>&& move2(T&& input) {
...
return static_cast<std::remove_reference_t<T>&&>(input);
}

Related

Why in below code return type is class type used for operator overloading?

I have been trying to understand operator overloading and did not get the use of return type as class type in the below program:
When I switch "overload" return type with "int" it works fine.
#include <iostream>
using namespace std;
class overload {
private:
int count;
public:
overload(int i)
: count(i)
{
}
overload operator++(int) //why return type is class type when i can use int
{
return (count++);
}
overload operator++() //why return type is class type when i can use int
{
count = count + 1;
return count;
}
void Display()
{
cout << "Count: " << count<<endl;
}
};
// Driver code
int main()
{
overload i(5);
overload post(5);
overload pre(5);
// this calls "function overload operator ++()" function
pre = ++i;
post = i++;
i.Display();
return 0;
}
The difference between the pre/post increment operators is that one works on the object directly (pre-increment: ++foo), and one needs to take a copy of the object and return that (post increment: foo++). A slightly more verbose way of writing this would be:
// return a new object that represents the old value
overload operator++(int)
{
overload oldValue(count); // take copy
count++; // increment this object
return oldValue;
}
// increment the count, and return a reference to this object
overload& operator++()
{
++count;
return *this;
}
Whilst you could return int (don't do that!), it will only lead to confusion. Effectively it would cause a few issues with code such as:
overload foo = ++someOtherFoo;
Which if you were to return int from ++, would effectively end up calling your constructor function (rather than copy constructor) to construct a new object. i.e.
overload foo = overload(++someOtherFoo);
That constructor might not be available, and so the code would fail.
If you want your object to automatically convert itself to an integer, then the correct way would be to overload the cast operator, e.g.
operator int () const
{
return count;
}
There are no restrictions on the return type of an overloaded operator. Here it can be int as well.
The code you show has the class type as return type to facilitate the other statements in the code as below if ever the constructor of the overload class is marked explicit;
For example with:
explicit overload(int i)
: count(i)
{
}
and
int operator++(int) //return type is int
{
return (count++);
}
int operator++() //return type is int
{
count = count + 1;
return count;
}
The following will fail to compile:
pre = ++i; //will not work
post = i++; //will not work
This is because the implicit copy assignment operator will no longer be viable for conversion from int to const overload.
See Demo
Note that the Canonical implementations of the prefix and postfix increment/decrement operators return overload& and overload respectively.
Although canonical form of pre-increment/pre-decrement returns a reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std::atomic return by value

C++ testing overloaded + operator

I'm simply adding two numeric arrays of size 3 and printing the result. So, if:
A = 4,6,1
B = 8,5,6
Then the result is 12,11,7. The problem for me is I am printing exponential numbers i.e. -1.28823e-231. Can anyone tell me why? I have tried to keep as little code in here as possible. First it's main() then the header then the source material. Many thanks.
NumericArray<double> doubArray5; //test + operator
cout << "doubArray5" << endl;
doubArray5 = doubArray2 + doubArray3;
for (int i = 0; i < doubArray5.Size(); i++)
cout << doubArray5[i] << endl;
cout << endl;
#ifndef NUMERICARRAY_H
#define NUMERICARRAY_H
#include "array.h"
#include <iostream>
namespace Cary
{
namespace Containers
{
template<typename T>
class NumericArray: public Array<T>
{
public:
NumericArray<T>(); //default constructor
NumericArray<T>(int i); //constructor with one argument
~NumericArray<T>(); //destructor
NumericArray<T>(const NumericArray<T>& source); //copy constructor
NumericArray<T>& operator = (const NumericArray<T>& arr1); //assignment operator
NumericArray<T> operator * (double factor) const; //scale
NumericArray<T>& operator + (const NumericArray<T>& arr2) const; //add
T dotProduct(const NumericArray<T>& na) const; //dot product
};
}
}
#ifndef NUMERICARRAY_CPP
#include "NumericArray.cpp"
#endif
#endif
template<typename T>
NumericArray<T>& NumericArray<T>::operator + (const NumericArray<T>& arr) const //add
{
if (Array<T>::Size() != arr.Size()) throw OutOfBoundsException();
NumericArray<T> tempArray = NumericArray(Array<T>::Size());
for (int i = 0; i < Array<T>::Size(); i++)
tempArray[i] = Array<T>::GetElement(i) + arr.GetElement(i);
return tempArray;
}
Idiomatically (i.e. based on the "behaves like int" guideline when overloading numeric operators), operator+() usually returns by value, not by reference, since the result of addition is a distinct value (or object) from either of those being added.
Specifically, as Mike Seymour also mentioned in comments, your operator+() is returning a reference to a local variable that ceases to exist when operator+() returns. That causes the caller to exhibit undefined behaviour if it subsequently attempts to use the returned reference.
You are returning a reference to a local variable (tempArray in operator +).
When the function returns, tempArray is destroyed. The caller then tries to use the reference to a now-destroyed object, and reads garbage.

Use const_cast to implement the move constructor

I have read this page about the move constructor. In that article, it use the template proxy to modify the temporary variable returned from function.
This is the implemention.
namespace detail {
template <class T>
struct proxy
{
T *resource_;
};
} // detail
template <class T>
class MovableResource
{
private:
T * resource_;
public:
explicit MovableResource (T * r = 0) : resource_(r) { }
~MovableResource() throw() { delete resource_; } // Assuming std:::auto_ptr like behavior.
MovableResource (MovableResource &m) throw () // The "Move constructor" (note non-const parameter)
: resource_ (m.resource_)
{
m.resource_ = 0; // Note that resource in the parameter is moved into *this.
}
MovableResource (detail::proxy<T> p) throw () // The proxy move constructor
: resource_(p.resource_)
{
// Just copying resource pointer is sufficient. No need to NULL it like in the move constructor.
}
MovableResource & operator = (MovableResource &m) throw () // Move-assignment operator (note non-const parameter)
{
// copy and swap idiom. Must release the original resource in the destructor.
MovableResource temp (m); // Resources will be moved here.
temp.swap (*this);
return *this;
}
MovableResource & operator = (detail::proxy<T> p) throw ()
{
// copy and swap idiom. Must release the original resource in the destructor.
MovableResource temp (p);
temp.swap(*this);
return *this;
}
void swap (MovableResource &m) throw ()
{
std::swap (this->resource_, m.resource_);
}
operator detail::proxy<T> () throw () // A helper conversion function. Note that it is non-const
{
detail::proxy<T> p;
p.resource_ = this->resource_;
this->resource_ = 0; // Resource moved to the temporary proxy object.
return p;
}
};
What about just add a constructor taking a const reference and use const_cast to change the variable to implement the move semantics like this.
MovableResource(const MovableResource& m)
{
MovableResource& afterM = const_cast<MovableResource&>(m);
afterM.swap(*this);
}
Does this introduce undefined behavior?
Implementing move semantics under the hood of a copy constructor interface is just asking for trouble. By using const_cast you are effectively fooling clients of your interface into believing that your constructor will leave m unmodified when it ends up clobbering its value. Consider the following code:
const MovableResource first(/* Some resource 'A' */);
MovableResource second(first);
// 'first', supposedly 'const' now has potentially a different value!
MovableResource (MovableResource &m) throw () // The "Move constructor" (note non-const parameter)
That is not a move constructor, that is a copy constructor. A proper move constructor takes an rvalue reference as input:
MovableResource (MovableResource &&m) throw ()
MovableResource & operator = (MovableResource &m) throw () // Move-assignment operator (note non-const parameter)
Likewise, that is a copy assignment operator. A proper move assignment operator takes an rvalue reference as input:
MovableResource & operator = (MovableResource &&m) throw ()

accessing operator overloading of class which is wrapped by std::shared_ptr

the idea is that I want a class which is wrapped by std::shared_ptr, can still be used
just like they weren't a pointer, for example the operator= which was defined in my class
can still be used after my class is wrapped by std::shared_ptr.
for example
template <class Ty> class shared_ptr_proxy : public std::shared_ptr<Ty> {
public:
template<class Other> shared_ptr_proxy& operator=(const Other& rhs)
{
(*this->get()) = rhs;
return *this;
}
template<class Other> explicit shared_ptr_proxy(Other * ptr)
: std::shared_ptr<Ty>(ptr){};
};
// usage :
shared_ptr_proxy<float> obj = shared_ptr_proxy<float>(new float);
obj = 3.14;
its work, but is there a way that i don't need to create shared_ptr_proxy or
inheriting a class from std::shared_ptr ?
and
if I do like this, is there a caveat that i should take care of?
It depends on what you want the proxy for. A full proxy might make it look entirely like you had the value, so you'd provide the conversion operators.
In such case, it might not be a good idea to inherit from shared_ptr, though, because you might be inheriting functions that you want to rely on the implicit conversions instead.
Compare how sorting orders the items:
#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
template <class Ty> class shared_ptr_proxy {
std::shared_ptr<Ty> ptr;
public:
template<class Other> explicit shared_ptr_proxy(Other * p)
: ptr(std::shared_ptr<Ty>(p)){};
template<class Other> shared_ptr_proxy& operator=(const Other& other)
{
*ptr = other;
return *this;
}
operator Ty& () { return *ptr; }
operator const Ty& () const { return *ptr; }
};
int main()
{
std::vector<shared_ptr_proxy<int> > vec {
shared_ptr_proxy<int>(new int(10)),
shared_ptr_proxy<int>(new int(11)),
shared_ptr_proxy<int>(new int(9))
};
vec.back() = 8; //use assignment
std::sort(vec.begin(), vec.end()); //sort based on integer (not pointer) comparison
for (unsigned i = 0; i != vec.size(); ++i) {
std::cout << vec[i] << ' '; //output stored values
}
}
#include <memory>
#include <vector>
#include <algorithm>
#include <iostream>
template <class Ty> class shared_ptr_proxy : public std::shared_ptr<Ty> {
public:
template<class Other> explicit shared_ptr_proxy(Other * p)
: std::shared_ptr<Ty>(p){};
template<class Other> shared_ptr_proxy& operator=(const Other& other)
{
*this->get()= other;
return *this;
}
operator Ty& () { return *this->get(); }
operator const Ty& () const { return *this->get(); }
};
int main()
{
std::vector<shared_ptr_proxy<int> > vec {
shared_ptr_proxy<int>(new int(10)),
shared_ptr_proxy<int>(new int(11)),
shared_ptr_proxy<int>(new int(9))
};
vec.back() = 8; //the only thing that works
std::sort(vec.begin(), vec.end()); //sort based on pointer values
for (unsigned i = 0; i != vec.size(); ++i) {
std::cout << vec[i] << ' '; //outputs addresses
}
}
operator= must be a member of the class that you're overloading. So no, you can't really do that non-intrusively.
No, you can't do this transparently, and it would probably be quite confusing if you could.
Sorry, I don't think you can get away without inheriting or a custom wrapper, you can not overload operator = outside the definition of shared_ptr, and inheritance is not recommended in this case due to the nature of shared_ptr. However if you write a custom wrapper you can make it generic enough that it works for every type.
It is only possible in C++11, and even there it is difficult. You need decltype and std::declval for deducing the return type of the operator, and rvalue references and std::forward to forward the parameters perfectly. See this question and its answers for examples.
And as mentioned in that question, I have a pointer wrapper class implemented: http://frigocoder.dyndns.org/svn/Frigo/Lang/ref
However it has some differences compared to what you want:
Both operator = (ref&) and operator = (ref&&) only copies pointers. However, due to this and the proxied copy constructor, the implicit operator = (const T&) does a copy construction and a pointer copy instead of assignment or taking the address. This is a conscious choice of mine, assignment can create problems if the object is shared, and taking pointer from a stack allocated object is unsafe.
Taking the return type of compound assignment operators like operator += does not work due to an unimplemented feature of GCC. This is no problem since they are reinterpreted: x += y calls x = (x + y), doing a copy/move construction and a pointer copy. This is also a conscious choice of mine, to keep the shared object unchanged.
Garbage collected with Boehm GC instead of reference counted. This is also a conscious choice of mine, reference counting is a pretty bad alternative to garbage collection.
Dereference shared pointer:
std::shared_ptr<float> obj(new float);
*obj = 3.14;

segmentation fault in overloading operator =

I just got a seg fault in overloading the assignment operator for a class FeatureRandomCounts, which has _rects as its pointer member pointing to an array of FeatureCount and size rhs._dim, and whose other date members are non-pointers:
FeatureRandomCounts & FeatureRandomCounts::operator=(const FeatureRandomCounts &rhs)
{
if (_rects) delete [] _rects;
*this = rhs; // segment fault
_rects = new FeatureCount [rhs._dim];
for (int i = 0; i < rhs._dim; i++)
{
_rects[i]=rhs._rects[i];
}
return *this;
}
Does someone have some clue? Thanks and regards!
*this = rhs;
calls operator=(), which is the function you are writing. Cue infinite recursion, stack overflow, crash.
Also, if you used a std::vector rather than a C-style array, you probably would not need to implement operator=() at all.
As mentioned, you have infinite recursion; however, to add to that, here's a foolproof way to implement op=:
struct T {
T(T const& other);
T& operator=(T copy) {
swap(*this, copy);
return *this;
}
friend void swap(T& a, T& b);
};
Write a correct copy ctor and swap, and exception safety and all edge cases are handled for you!
The copy parameter is passed by value and then changed. Any resources which the current instance must destroy are handled when copy is destroyed. This follows current recommendations and handles self-assignment cleanly.
#include <algorithm>
#include <iostream>
struct ConcreteExample {
int* p;
std::string s;
ConcreteExample(int n, char const* s) : p(new int(n)), s(s) {}
ConcreteExample(ConcreteExample const& other)
: p(new int(*other.p)), s(other.s) {}
~ConcreteExample() { delete p; }
ConcreteExample& operator=(ConcreteExample copy) {
swap(*this, copy);
return *this;
}
friend void swap(ConcreteExample& a, ConcreteExample& b) {
using std::swap;
//using boost::swap; // if available
swap(a.p, b.p); // uses ADL (when p has a different type), the whole reason
swap(a.s, b.s); // this 'method' is not really a member (so it can be used
// the same way)
}
};
int main() {
ConcreteExample a (3, "a"), b (5, "b");
std::cout << a.s << *a.p << ' ' << b.s << *b.p << '\n';
a = b;
std::cout << a.s << *a.p << ' ' << b.s << *b.p << '\n';
return 0;
}
Notice it works with either manually managed members (p) or RAII/SBRM-style members (s).
*this = rhs; // segment fault
This is definitively not the way to do it. You call = recursively, not calling the built in assignment operator. Assign variables one by one. Don't be lazy.
The following line:
*this = rhs; // segment fault
will recursively call your operator=() function resulting in a stack overflow.
You should probably replace it with straight-forward assignments of the various member fields.
As Neil said, using something like std::vector<> will remove much of the responsibility away from your code. If for whatever reason you can't or don't want to use std::vector<>, you might also want to consider using the 'swap idiom' for your assignment operator. This will make the function exception safe (if the allocation of the memory for FeatureCount array fails and throws an exception, the original object that's being assigned to will be left unchanged). Something like the following:
void FeatureRandomCounts::swap( FeatureRandomCounts& other)
{
FeatureCount* tmp_rects = other._rects;
int tmp_dim = other._dim; // or whatever type _dim is
// similarly for other members of FeatureRandomCounts...
// now copy the other contents to
this->_rects = other._rects;
this->_dim = other._dim;
// assign other members of rhs to lhs
other._rects = tmp_rects;
other._dim = tmp_dim;
// etc.
return;
}
Now your assignment can look like:
FeatureRandomCounts & FeatureRandomCounts::operator=(const FeatureRandomCounts &rhs)
{
FeatureRandomCounts tmp( rhs); // make a copy
tmp.swap( *this); // swap the contents of the copy and *this
return *this;
// the contents of tmp (which has the old
// stuff that was in *this) gets destructed
}
Note that you need a proper copy constructor for this to work, but given the Big 3 rule you already need a proper copy ctor.