Can move semantics be used if the class member is not a pointer.
Aug 9, 2018 at 7:19pm UTC
Hi ppl :)
I was recently trying to understand move semantics of c++ 11 and found that most of the examples available online demonstrate this using a class member that is of pointer type. Like below :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#include <iostream>
#include <string.h>
class Str
{
private :
char *str;
friend Str operator +(const Str&, const Str&);
public :
Str() = default ;
Str(const char * s)
{
str = new char [strlen(s) + 1];
strcpy(str, s);
}
Str(Str&& s) //Move constructor
{
std::cout << "move constructor called\n" ;
str = s.str;
s.str = nullptr ;
}
virtual ~Str()
{
delete [] str;
}
int size() const
{
return strlen(str);
}
void showStr()
{
for (int i {0}; i < str[i] != '\0' ; ++i)
std::cout << str[i];
std::cout << std::endl;
}
};
Str operator +(const Str& a, const Str& b)
{
char * c = new char [a.size() + b.size() + 1];
strcpy(c, a.str);
strcpy(c + a.size(), b.str);
return Str(c);
}
void f(Str s)
{
s.showStr();
}
int main()
{
Str s1{"hello " };
Str s2{"everyone" };
f(std::move(s1 + s2)); //will invoke Move constructor
return 0;
}
I am looking for an example where the move semantics is applied for a non pointer member, like a vector.
To be precise, how would we write move constructor if "str" were a vector instead of char* above were a vector.
Test(std::vector<int >&& vec) ??
Thanks for the help :)
Last edited on Aug 9, 2018 at 7:20pm UTC
Aug 9, 2018 at 7:43pm UTC
1 2 3 4
Test(std::vector<int >&& vec)
: str(std::move(vec))
{
}
Aug 9, 2018 at 8:24pm UTC
Thanks Peter87 :)
Aug 9, 2018 at 10:59pm UTC
To note, the call to move in
f(std::move(s1 + s2)) is redundant, because the expression s1+s2 is an rvalue.
In fact, it's actually worse than redundant, because the explicit move prevents
copy elision , forcing a move or copy where neither a move nor copy is necessary. This isn't just an optimization : without that move() call, no copy or move operation occurs, even conceptually.
Consider:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
#include <utility>
#include <iostream>
struct noisy
{
explicit noisy(int v = 0)
: value(v)
{
std::cout << value << " : construct\n" ;
}
noisy(const noisy &that)
: value(that.value)
{
std::cout << value << " : copy construct\n" ;
}
noisy(noisy &&that)
: value(that.value)
{
std::cout << value << " : move construct\n" ;
}
noisy &operator =(const noisy &that)
{
value = that.value;
std::cout << value << " : copy assign\n" ;
return *this ;
}
noisy &operator =(noisy &&that)
{
value = that.value;
std::cout << value << " : move assign\n" ;
return *this ;
}
~noisy()
{
std::cout << value << " : destroy\n" ;
}
int value;
};
noisy
operator +(noisy const &a, noisy const &b)
{
return noisy{ a.value + b.value };
}
void
f(noisy n)
{
std::cout << n.value << "\n" ;
}
int
main()
{
std::cout << "Without std::move:\n" ;
{
noisy a{ 24 };
noisy b{ 18 };
f(a + b);
}
std::cout << "\n\nWith std::move:\n" ;
{
noisy a{ 24 };
noisy b{ 18 };
f(std::move(a + b));
}
}
Without std::move:
24 : construct
18 : construct
42 : construct
42
42 : destroy
18 : destroy
24 : destroy
With std::move:
24 : construct
18 : construct
42 : construct
42 : move construct
42
42 : destroy
42 : destroy
18 : destroy
24 : destroy
http://coliru.stacked-crooked.com/a/bee5dc66c4002acb
Last edited on Aug 9, 2018 at 11:08pm UTC
Topic archived. No new replies allowed.