Skip to content

Instantly share code, notes, and snippets.

@farhangamary
Created March 10, 2024 23:27
Show Gist options
  • Select an option

  • Save farhangamary/307aa8eaa020dcaeb9206630aba325b5 to your computer and use it in GitHub Desktop.

Select an option

Save farhangamary/307aa8eaa020dcaeb9206630aba325b5 to your computer and use it in GitHub Desktop.
An easy to understand sample of C++ move semanitcs, rvalue, lvalue, move, forward, copy and move constructors
#include <iostream>
#include <string.h>
class SampleStr
{
char *str_data;
int length;
public:
SampleStr(const char *data = "") : length(0), str_data(nullptr)
{
std::cout << "Regular Constructor." << std::endl;
length = strlen(data);
str_data = new char(length + 1);
strcpy(str_data, data);
}
SampleStr(const SampleStr &other) : str_data(nullptr), length(other.length)
{
std::cout << "Copy C." << std::endl;
if (other.str_data)
{
str_data = new char(length + 1);
strcpy(str_data, other.str_data);
}
}
SampleStr(SampleStr &&other) noexcept : str_data(nullptr), length(0)
{
std::cout << "Move C." << std::endl;
str_data = other.str_data;
length = other.length;
other.str_data = nullptr;
other.length = 0;
}
~SampleStr()
{
std::cout << "D." << std::endl;
delete[] str_data;
}
char *get_str_data() const
{
return str_data;
}
};
void call_s(SampleStr &sample)
{
const char *str_data = sample.get_str_data();
std::cout
<< "Called by ref - str data is:\t"
<< (str_data ? str_data : "NULL") << std::endl;
}
void call_s(SampleStr &&sample)
{
const char *str_data = sample.get_str_data();
std::cout
<< "Called by ref with rvalue ref - str data is:\t"
<< (str_data ? str_data : "NULL") << std::endl;
}
int main(int argsc, char *args[])
{
std::cout << "Hi and welcome!" << std::endl;
const char *initial_str = "constStr";
SampleStr sampleStr(initial_str); // Regular object
SampleStr &&sampleStrRRef = SampleStr(sampleStr); // A reference to a rvalue which is a copy object
call_s(sampleStr); // by ref!
call_s(std::forward<SampleStr>(sampleStrRRef)); // perfect forward!! - the original rvalue ref is passed to the function.
SampleStr movedSampelStr = SampleStr(std::move(sampleStr)); // The value category is casted to rvalue and the move constructr will be used.
SampleStr forwarderSampleStr = SampleStr(std::forward<SampleStr>(movedSampelStr)); // Again perfect forward! an l value is passed, but the move constructor is called however the resource is not stolen and the ownership is not changed.!
call_s(sampleStr); // Object is valid but the content not! it's moved and the ownership is changedf.
std::cout << "End." << std::endl;
return EXIT_SUCCESS;
}
/******** output ****************************
$ g++ -o check mv_cp.cpp
$ ./check
Hi and welcome!
Regular Constructor.
Copy C.
Called by ref - str data is: constStr
Called by ref with rvalue ref - str data is: constStr
Move C.
Move C.
Called by ref - str data is: NULL
End.
D.
D.
D.
D.
************************************************/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment