Boost::ptr_vector changing elements order - c++

Please, could someone tell me how to switch the location of two elements from the same ptr_vector without
new dynamic memory allocation. That is, I want to do the same as below using std::vector, but with boost::ptr_vector.
Moreover, this has to be done using indexes, instead of ptr_vector::iterator.
void switch( vector<int>& V , size_t i , size_t j){
int a = V[ j ];
V[ j ] = V[ i ];
V[ i ] = a;
}
Thanks all.

(Untested), I'd imagine it has to be something like:
void switch( ptr_vector<int>& V , size_t i , size_t j){
auto p = V.replace(i, nullptr); // should get you the value there..
auto k = V.replace(j, p); // should get you the value there..
auto res = V.replace(i, k);
assert(res == nullptr); // this should be the case...
}

boost::ptr_vector<T> v;
size_t i = whatever, j = whatever;
// Put this in a separate function
// Do NOT use it as a subexpression or you may (?) forfeit exception safety
v.replace(j, v.replace(i, &v[j]).release()).release();

You can just swap the element values:
using std::swap;
swap(v[1], v[2]);
This will do exactly what you expected from the std::vector case. Here's a demo using a sentinel type to trace allocations: Live On Coliru (it doesn't do any new allocations for the swap)
Prints:
static void* X::operator new(size_t)(4)
X::X(int)(1)
static void* X::operator new(size_t)(4)
X::X(int)(2)
static void* X::operator new(size_t)(4)
X::X(int)(3)
static void* X::operator new(size_t)(4)
X::X(int)(4)
X[1] X[2] X[3] X[4]
===============================
swapping v[1] and v[2]:
X::X(X&&)(X[2])
X& X::operator=(X&&)(X[3])
X& X::operator=(X&&)(X[2])
X::~X()
===============================
X[1] X[3] X[2] X[4] X::~X()
static void X::operator delete(void*)
X::~X()
static void X::operator delete(void*)
X::~X()
static void X::operator delete(void*)
X::~X()
static void X::operator delete(void*)
Full Program
#include <boost/ptr_container/ptr_vector.hpp>
struct X {
X(int i) : _i(i) { std::cout << __PRETTY_FUNCTION__ << "(" << i << ")" << "\n"; }
X(X && x) : _i(x._i) { std::cout << __PRETTY_FUNCTION__ << "(" << x << ")" << "\n"; }
X(X const& x) : _i(x._i) { std::cout << __PRETTY_FUNCTION__ << "(" << x << ")" << "\n"; }
~X() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
void* operator new(size_t n) {
std::cout << __PRETTY_FUNCTION__ << "(" << n << ")" << "\n";
return ::operator new(n);
}
void operator delete(void* px) {
std::cout << __PRETTY_FUNCTION__ << "\n";
return ::operator delete(static_cast<X*>(px));
}
X& operator=(X const& x) {
_i = x._i;
std::cout << __PRETTY_FUNCTION__ << "(" << x << ")" << "\n";
return *this;
}
X& operator=(X && x) {
_i = x._i;
std::cout << __PRETTY_FUNCTION__ << "(" << x << ")" << "\n";
return *this;
}
friend std::ostream& operator<<(std::ostream& os, X const& x) {
return os << "X[" << x._i << "]";
}
private: int _i;
};
int main()
{
boost::ptr_vector<X> v;
v.push_back(new X(1));
v.push_back(new X(2));
v.push_back(new X(3));
v.push_back(new X(4));
for (auto& p : v)
std::cout << p << " ";
std::cout << "\n===============================\nswapping v[1] and v[2]:\n";
using std::swap;
swap(v[1], v[2]);
std::cout << "\n===============================\n";
for (auto& p : v)
std::cout << p << " ";
}

Related

std::forward and rvalue references in a class

I've been reading about std::forward and I think I understand it well, but I don't think I understand it well enough to use it proficiently enough.
I have a template class that implements a container and has a method called insert. I wanted this method to accept constant references and rvalue references so that if the inserted element is a rvalue reference, it is moved into the container, not copied. For this, I first overloaded the insert method like this:
template <typename U>
void do_some_work(U&& x) noexcept
{
m_data = std::forward<U>(x);
}
void insert(const T& x)
{
do_some_work(x);
}
void insert(T&& x) {
do_some_work(std::forward<T>(x);
}
The problem is, these two functions now have to call an "inner" function that implements the assertion. If the functions are small, I guess this is not a problem, but if they are large, it is best to use templates, like this
template <typename U>
void insert(U&& x)
{
do_some_work(std::forward<U>(x);
}
QUESTION 1: Is this correct?
Now, I want to do the same but with std::vector.
void insert_vector(const std::vector<T>& v) noexcept {
for (std::size_t i = 0; i < v.size(); ++i) {
do_some_work(v[i]);
}
}
void insert_vector(std::vector<T>&& v) noexcept
{
for (std::size_t i = 0; i < v.size(); ++i)
{
do_some_work(std::forward<T>(v[i]));
}
}
QUESTION 2: How do I collapse the insert_vector functions into a single one so that the call to do_some_work is done with
rvalue references when the vector is a rvalue reference (specified with std::move, for example),
constant reference when the vector is not given as an rvalue reference, like in (4) of the MWE below. The following does not work for me
template <typename U>
void insert_vector(U&& v) noexcept
{
for (std::size_t i = 0; i < v.size(); ++i)
{
do_some_work(std::forward<T>(v[i]));
}
}
Here is a minimum working example:
#include <iostream>
#include <vector>
template <typename T>
class my_class
{
private:
T m_data;
private:
template <typename U>
void do_some_more_work(U&& x) noexcept {
m_data = std::forward<U>(x);
}
template <typename U>
void do_some_work(U&& x) noexcept {
do_some_more_work(std::forward<U>(x));
}
public:
void insert(const T& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_work(x);
}
void insert(T&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_work(std::forward<T>(x));
}
void insert_vector(const std::vector<T>& v) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
for (std::size_t i = 0; i < v.size(); ++i) {
do_some_work(v[i]);
}
}
void insert_vector(std::vector<T>&& v) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
for (std::size_t i = 0; i < v.size(); ++i) {
do_some_work(std::forward<T>(v[i]));
}
}
};
struct my_struct {
my_struct() noexcept = default;
my_struct(int v) noexcept : m_v(v) { }
my_struct(const my_struct& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = s.m_v;
}
my_struct(my_struct&& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = std::move(s.m_v); // not need, but whatever
s.m_v = -1;
}
my_struct& operator= (const my_struct& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = s.m_v;
return *this;
}
my_struct& operator= (my_struct&& s) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_v = std::move(s.m_v); // not need, but whatever
s.m_v = -1;
return *this;
}
int m_v;
};
int main() {
my_class<my_struct> mc;
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(1.1)\n";
my_struct s{3};
std::cout << s.m_v << '\n';
mc.insert(s);
std::cout << s.m_v << '\n';
}
{
std::cout << "-------------------------------------------\n";
std::cout << "(1.2)\n";
const my_struct s{3};
std::cout << s.m_v << '\n';
mc.insert(s);
std::cout << s.m_v << '\n';
}
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(2.1)\n";
mc.insert(my_struct{5});
}
{
std::cout << "-------------------------------------------\n";
std::cout << "(2.2)\n";
my_struct s{5};
std::cout << s.m_v << '\n';
mc.insert(std::move(s));
std::cout << s.m_v << '\n';
}
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(3.1)\n";
std::vector<my_struct> v(5);
for (std::size_t i = 0; i < v.size(); ++i) { v[i] = my_struct(i); }
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
mc.insert_vector(v);
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
}
{
std::cout << "-------------------------------------------\n";
std::cout << "(3.2)\n";
const std::vector<my_struct> v = []() {
std::vector<my_struct> v(5);
for (std::size_t i = 0; i < v.size(); ++i) { v[i] = my_struct(i); }
return v;
}();
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
mc.insert_vector(v);
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
}
std::cout << "===========================================\n";
{
std::cout << "-------------------------------------------\n";
std::cout << "(4)\n";
std::vector<my_struct> v(5);
for (std::size_t i = 0; i < v.size(); ++i) { v[i] = my_struct(i); }
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
mc.insert_vector(std::move(v));
for (const auto& s : v) { std::cout << s.m_v << ' '; } std::cout << '\n';
}
}
I think I found a way to solve this issue. I used the same "technique" as with the regular insert methods. The full implementation of my_class is this. Unfortunately, I could not make a single insert method.
template <typename T>
class my_class {
private:
T m_data;
private:
template <typename U>
void do_some_more_work(U&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
m_data = std::forward<U>(x);
}
template <typename U>
void do_some_work(U&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_more_work(std::forward<U>(x));
}
public:
template <typename U>
void insert(U&& x) noexcept {
std::cout << __PRETTY_FUNCTION__ << '\n';
do_some_work(std::forward<U>(x));
}
template <typename U>
void insert_vector(U&& v) noexcept {
using elem_t = typename std::remove_reference_t<U>::value_type;
// this is used here for testing purposes.
static_assert(std::is_same_v<elem_t, my_struct>);
std::cout << __PRETTY_FUNCTION__ << '\n';
for (std::size_t i = 0; i < v.size(); ++i) {
if constexpr (std::is_same_v<std::vector<elem_t>, U>) {
do_some_work(std::forward<T>(v[i]));
}
else {
do_some_work(v[i]);
}
}
}
};

Try to pass an object to a same template class to copy

I work actually to understand the concept of template and implement a simple one. I manage to almost cases execpt one to code a constructor to copy an instance of same class.
#include <iostream>
// template <typename T>
template <class T>
class vec2 {
private:
static int instance;
T const x;
T const y;
public:
vec2() : x(0), y(0) {
std::cout << "Default constructor" << std::endl;
vec2<T>::instance++;
return;
}
vec2(T const &x, T const &y) : x(x), y(y) {
std::cout << "Parametric constructor" << std::endl;
vec2<T>::instance++;
return;
}
vec2(vec2<T> const & src) {
*this = src;
std::cout << "Copy constructor" << std::endl;
vec2<T>::instance++;
return;
}
~vec2(){
std::cout << "Destructor" << std::endl;
vec2<T>::instance--;
return;
}
vec2 & operator=(vec2 const & rhs) {
this->x = rhs.get_x();
this->y = rhs.get_y();
return *this;
}
// get
static int get_instance() {
return vec2<T>::instance;
}
T get_x() const {
return this->x;
}
T get_y() const {
return this->y;
}
};
template <class T>
std::ostream & operator<<(std::ostream & out, vec2<T> const & rhs) {
out << "[ " << rhs.get_x() << ", " << rhs.get_y() << " ]";
return out;
}
template <class T>
int vec2<T>::instance = 0;
int main() {
vec2<float> a;
vec2<int> b(21, 42);
vec2<float> c(21.21f, 42.42f);
vec2<bool> d(true, false);
vec2<int> e(b);
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << c << std::endl;
std::cout << d << std::endl;
std::cout << e << std::endl;
std::cout << "a.get_x(): " << a.get_x() << std::endl;
std::cout << "a.get_y(): " << a.get_y() << std::endl;
std::cout << "b.get_x(): " << b.get_x() << std::endl;
std::cout << "b.get_y(): " << b.get_y() << std::endl;
std::cout << "c.get_x(): " << c.get_x() << std::endl;
std::cout << "c.get_y(): " << c.get_y() << std::endl;
std::cout << "d.get_x(): " << d.get_x() << std::endl;
std::cout << "d.get_y(): " << d.get_y() << std::endl;
return (0);
}
here the error message, but I'm not expert te read it, and i don't understand what i must change in my code. So if anybody I have an idea to help a newbee in C++, that's can be awesome.
clang++ -std=c++11 -Wconversion *.cpp && ./a.out
main.cpp:24:2: error: constructor for 'vec2<int>' must explicitly initialize the
const member 'x'
vec2(vec2<T> const & src) {
^
main.cpp:72:12: note: in instantiation of member function 'vec2<int>::vec2'
requested here
vec2<int> e(b);
^
main.cpp:9:10: note: declared here
T const x;
^
main.cpp:24:2: error: constructor for 'vec2<int>' must explicitly initialize the
const member 'y'
vec2(vec2<T> const & src) {
^
main.cpp:10:10: note: declared here
T const y;
^
main.cpp:38:11: error: cannot assign to non-static data member 'x' with
const-qualified type 'const int'
this->x = rhs.get_x();
~~~~~~~ ^
main.cpp:25:9: note: in instantiation of member function 'vec2<int>::operator='
requested here
*this = src;
^
main.cpp:72:12: note: in instantiation of member function 'vec2<int>::vec2'
requested here
vec2<int> e(b);
^
main.cpp:9:10: note: non-static data member 'x' declared const here
T const x;
~~~~~~~~^
main.cpp:39:11: error: cannot assign to non-static data member 'y' with
const-qualified type 'const int'
this->y = rhs.get_y();
~~~~~~~ ^
main.cpp:10:10: note: non-static data member 'y' declared const here
T const y;
~~~~~~~~^
4 errors generated.
As #Sam Varshavchik said in the comments, the problem is that you don't initialize your const members in your copy-constructor. Here is the correct implementation:
vec2(vec2<T> const & src) : x(src.get_x()), y(src.get_y()) { //<-- initialization of const members
std::cout << "Copy constructor" << std::endl;
vec2<T>::instance++;
return;
}
Also, *this = src; does feel all kinds of wrong.
here my original class code where i make a copy with *this = src and the result work great. So the question why that's work with regular class and not with the template ?
Plus I imagine the behavior with the regular class, the adress stay the same.
And the method to init all member can be complicated if the is a lot members variables in the class ?
main.c
#include "Vec2.hpp"
#include <iostream>
int main() {
Vec2 a;
Vec2 b(21,42);
Vec2 c(a);
std::cout << a << std::endl;
std::cout << "c.get_x(): " << c.get_x() << std::endl;
std::cout << "c.get_y(): " << c.get_y() << std::endl;
std::cout << "b.get_x(): " << b.get_x() << std::endl;
std::cout << "b.get_y(): " << b.get_y() << std::endl;
std::cout << "a.get_x(): " << a.get_x() << std::endl;
std::cout << "a.get_y(): " << a.get_y() << std::endl;
a = b;
std::cout << "a.get_x(): " << a.get_x() << std::endl;
std::cout << "a.get_y(): " << a.get_y() << std::endl;
return 0;
}
Vec2.cpp
#ifndef VEC2_H
# define VEC2_H
#include <iostream>
class Vec2 {
public:
Vec2(); // canonical
Vec2(float const x, float const y);
Vec2(Vec2 const &); // canonical
~Vec2(); // canonical
Vec2 & operator=(Vec2 const & rhs); // canonical
static int get_instance();
float get_x() const ;
float get_y() const ;
private:
static int instance;
float x;
float y;
};
std::ostream & operator<< (std::ostream & out, Vec2 const & rhs);
#endif
vec2.hpp
#include "Vec2.hpp"
#include <iostream>
Vec2::Vec2() : x(0), y(0) {
std::cout << "Default constructor" << std::endl;
Vec2::instance++;
return;
}
Vec2::Vec2(float const x, float const y) : x(x), y(y) {
std::cout << "Parametric constructor" << std::endl;
Vec2::instance++;
return;
}
Vec2::Vec2(Vec2 const & src) {
*this = src;
std::cout << "Copy constructor" << std::endl;
Vec2::instance++;
return;
}
Vec2::~Vec2() {
std::cout << "Destructor" << std::endl;
Vec2::instance--;
return;
}
Vec2 & Vec2::operator=(Vec2 const & rhs) {
this->x = rhs.get_x();
this->y = rhs.get_y();
return *this;
}
int Vec2::get_instance(){
return Vec2::instance;
}
float Vec2::get_x() const {
return this->x;
}
float Vec2::get_y() const {
return this->y;
}
std::ostream & operator<< (std::ostream & out, Vec2 const & rhs) {
out << "[ " << rhs.get_x() << ", " << rhs.get_y() << " ]";
return out;
}
int Vec2::instance = 0;

Are const data member allowed to change outside the class?

If a class has a const reference data member that happens to change outside the scope of such class, is this undefined behaviour?
As an example, let's consider the following C++ code:
#include <iostream>
class A {
int x;
public:
A(int x): x(x){}
void change(int y){
x = y;
}
friend std::ostream & operator << (std::ostream & os, const A & a){
os << a.x;
return os;
}
};
class B {
const A & a;
public:
B(const A & a) : a(a) {}
friend std::ostream & operator << (std::ostream & os, const B & b){
os << b.a;
return os;
}
};
int main(){
A a(1);
B b(a);
std::cout << a << std::endl;
std::cout << b << std::endl;
a.change(2);
std::cout << a << std::endl;
std::cout << b << std::endl;
}
My compiler was able to execute it correctly and the debugger indicated that the x of B::a was changed.
Thank you for you help!
It is not undefined behavior. The const reference that is a member of B only means that an instance of B may not change it via that reference. Because it is a reference, however, something else may change it -- including other members of B that have their own non-const reference to the same instance of A.
Compare the addition of the member c to your existing B class, and note that we are changing it successfully within B::changeA() via the non-const reference and also from C::change() down in main():
#include <iostream>
class A {
int x;
public:
A(int x): x(x){}
void change(int y){
x = y;
}
friend std::ostream & operator << (std::ostream & os, const A & a){
os << a.x;
return os;
}
};
class C
{
A& a;
public:
C(A& a) : a{a} {}
void change(int y) { a.change(y); }
};
class B {
const A & a;
C& c;
public:
B(const A & a, C& c) : a(a), c{c} {}
friend std::ostream & operator << (std::ostream & os, const B & b){
os << b.a;
return os;
}
void changeA(int y) { c.change(y); }
};
int main(){
A a(1);
C c(a);
B b(a,c);
std::cout << a << ' ' << b << '\n';
a.change(2);
std::cout << a << ' ' << b << '\n';
b.changeA(3);
std::cout << a << ' ' << b << '\n';
c.change(4);
std::cout << a << ' ' << b << '\n';
}
See it run live on Coliru, which prints:
1 1
2 2
3 3
4 4
You may not change an object using a constant reference to it but you may change the object itself if it is not constant or using a non-constant reference to the object.
Consider the following demonstrative program.
#include <iostream>
int main()
{
int x = 10;
int &rx = x;
const int &crx = x;
std::cout << "rx = " << rx << '\n';
std::cout << "crx = " << crx << '\n';
rx = 20;
std::cout << "rx = " << rx << '\n';
std::cout << "crx = " << crx << '\n';
return 0;
}
Its output is
rx = 10
crx = 10
rx = 20
crx = 20
It is the same as using a pointer to constant data. For example
#include <iostream>
int main()
{
int x = 10;
int *px = &x;
const int *cpx = &x;
std::cout << "*px = " << *px << '\n';
std::cout << "*cpx = " << *cpx << '\n';
*px = 20;
std::cout << "*px = " << *px << '\n';
std::cout << "*cpx = " << *cpx << '\n';
return 0;
}

Is there a way to avoid calling constructor and destructor for perfect forwarding to a function?

I am trying to pass literal to a perfect forwarding setter, but this results in object construction, movement and destruction instead. I am looking for a more efficient way to do this.
struct TStruct {
TStruct(int va) : a(va) {
std::cout << "- TStruct(" << va << ")" << std::endl;
}
TStruct(const TStruct& other) :
a(other.a)
{
std::cout << "- TStruct(const TStruct& )" << std::endl;
}
TStruct(TStruct&& other) :
a(std::exchange(other.a, 0))
{
std::cout << "- TStruct(const TStruct&&)" << std::endl;
}
TStruct& operator=(const TStruct& rhs) {
std::cout << "- TStruct operator= const& " << std::endl;
// check for self-assignment
if(&rhs == this) return *this;
a = rhs.a;
return *this;
}
TStruct& operator=(TStruct&& rhs) {
std::cout << "- TStruct operator=&&" << std::endl;
// check for self-assignment
if(&rhs == this) return *this;
a = std::exchange(rhs.a, 0);
return *this;
}
~TStruct() {
std::cout << "~ TStruct() destructor with " << a << std::endl;
}
int a = 1;
};
struct TPerfectForward {
template<class T>
TPerfectForward(T&& tsv) : ts(std::forward<T>(tsv)) {}
template<class T>
void set(T&& tsv) { ts = std::forward<T>(tsv); }
TStruct ts;
};
std::cout << "TPerfectForward (5)" << std::endl;
TPerfectForward pf(5);
std::cout << "TPerfectForward set(4)" << std::endl;
pf.set(4);
This gives following results with gcc 7.4.0 on Ubuntu:
TPerfectForward (5);
- TStruct(5)
TPerfectForward set(4)
- TStruct(4)
- TStruct operator=&&
~ TStruct() destructor with 0
I would like these results better:
TPerfectForward (5)
- TStruct(5)
TPerfectForward set(4)
- TStruct(4)
Is there a way to avoid calling move operator and destructor when perfect forwarding to a function?

rvalue as initialiser to construct an object

I am new to programming. sorry for my bad english.
I have tried to use rvalue as initialiser to initial objects.
So, according to the code, it would print out what are the used constructor and assignment operator.
But turned out object "what2" and "what3", those don't print out anything.
here is the code:
#include <iostream>
using namespace std;
class X{
public:
int x;
X()= default;
X(int num):x{num}{}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
std::cout << x << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const X& a,const X& b){
X tmp{};
tmp.x = a.x +b.x;
return tmp;
}
int main(int argc, const char * argv[]) {
X a{7} , b{11};
X what1;
cout << "---------------" << endl;
what1 = a+b;
cout << "---------------" << endl;
X what2{a+b};
cout << "---------------" << endl;
X what3 = a+b;
cout << "---------------" << endl;
std::cout << what1.x << std::endl;
std::cout << what2.x << std:: endl;
std::cout <<what3.x << std::endl;
return 0;
}
the output is:
---------------
move assignment
---------------
---------------
---------------
18
18
18
Program ended with exit code: 0
only "what1" uses assignment properly.
so, how can i use rvalue to initial an object? and using operator= to initial an object?
thank you very much.
Your code could result in move operations being used, but your compiler has chosen to elide those moves and allocate the return of operator+ directly at the call site. You can see this happening if you disable copy elision in your compiler (-fno-elide-constructors in GCC or Clang).
Your move constructor and assignment operator will be successfully used in contexts in which copy elision is not permitted, such as this:
X what2 { std::move(what1) }; //can't elide copy, move constructor used
The following code triggers more of your constructors/operators, check it out to see which trigger in what cases
#include <iostream>
using namespace std;
class X{
public:
int x;
X()
{
x = 0;
std::cout << "constructor" << std::endl;
}
X(int num):x{num}
{
std::cout << "list initilizer" << std::endl;
}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const X& a,const X& b){
X tmp{};
tmp.x = a.x +b.x;
return tmp;
}
int main(int argc, const char * argv[]) {
X a{7} , b{11};
cout << "---------------" << endl;
X what1;
cout << "---------------" << endl;
what1 = a+b;
cout << "---------------" << endl;
X what2(a+b);
cout << "---------------" << endl;
X what3 = X(a);
cout << "---------------" << endl;
X what4 = X();
cout << "---------------" << endl;
X what5 = std::move(what1);
cout << "---------------" << endl;
what5 = std::move(what1);
cout << "---------------" << endl;
what5 = what1;
cout << "---------------" << endl;
return 0;
}
GCC provides the -fno-elide-constructors option to disable copy-elision. if you want to elide the copy-elision then use flag -fno-elide-constructors. Refer https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization/27916892#27916892 for more detail