Reputation: 357
I have been researching about Move constructors compared to Copy constructors. From what I have read on stackoverflow and other sources of information, was more related on how to 'invoke' them, but I haven't been able to find a clear answer as to if they are 'always' more efficient than copy constructors, maybe I'm just searching for the wrong stuff.
Anyways the reason I am asking is because the following scenario WOULD make the Move Constructor more efficient than the Copy constructor:
class Test {
std::string *name;
std::vector<std::string> *friends;
public:
Test() : name{nullptr}, friends{nullptr} {} // If not initialized they may be pointing to random memory
Test(std::string name, std::vector<std::string> friends) : name{nullptr}, friends{nullptr} {
this->name = new std::string{std::move(name)}; // Is the std::move necessary, or is 'name' still considered an r-value even though it has a variable name now (if it had been passed as an r-value to the constructor in the first place)
this->friends = new std::vector<std::string>{std::move(friends)}; // Is the std::move necessary, or is 'friends' still considered an r-value even though it has now got a variable name (if it had been passed as an r-value to the constructor in the first place)
}
// Copy constructor
Test(const Test &source) : name{nullptr}, friends{nullptr} {
name = new std::string{*source.name};
friends = new std::vector<std::string>{*source.friends};
}
// Move constructor
Test(Test &&source) noexcept : name{source.name}, friends{source.friends} {
source.name = nullptr;
source.friends = nullptr;
}
// Destructor
~Test() {
delete name;
delete friends;
}
};
From here on and out, or in-fact at any point in my post, correct me please if I state something incorrectly.
Here from my understand the move constructor would definitely be much more efficient especially as the vector and string sizes get bigger, due to the fact that we are copying a memory address instead of objects by value. It would be great help if I could get feedback on the two comments/questions that I left behind in my code, about the std::move and if it was necessary or not in that scenario, I explain my thought process in the two similar comments/questions.
Now here is where my question arises... because when I don't have any attributes/member variables which are pointers to anything, I am unsure, or in-fact I'm more lenient to the fact that Move Constructors won't be faster than Copy Constructors, but again I need some help for confirmation on this one.
Here is the following class which is similar, but refactored into code which suites the attributes/member variables which it contains:
class Test {
std::string name;
std::vector<std::string> friends;
public:
Test() : name{}, friends{} {} // 'name' is initialzied to "" and 'friends' I am not quite sure what it is initialized to, maybe just an empty vector, but I'm not sure
Test(std::string name, std::vector<std::string> friends) : name{name}, friends{friends} {} // No need for any code inside the code block --- is that what it's called? Or just code brackets? Or what? lol
// Copy constructor
Test(const Test &source) : name{source.name}, friends{source.friends} {} // Again, no need for any extra code in the -- whatever it's called --
// Move constructor
Test(Test &&source) noexcept : name{source.name}, friends{source.friends} {}
// Destructor
~Test() {} // No need to define one our selves but I just left it like this anyways, just removed the 'delete' statements
};
When I look at the code above, I can't think of anyway that Move constructor could be any faster or efficient than the copy Copy Constructor. In this case I can't think of anyway to make the Move Constructor any faster/efficient.
Questions that may be answered apart from some questions already asked above, either in the code or in one of the paragraphs, I would highly appreciate if the questions in the comments of the code or in the paragraphs were also answered:
Test
definition?Test
class?Upvotes: 0
Views: 1093
Reputation: 217135
Are Move Constructors 'always' more efficient than Copy Constructors?
Both can have custom implementation, so "evil" classes might make inefficient move, and correct copy.
For regular classes, move
should be more efficient or equivalent to copy.
When I look at the code above, I can't think of anyway that Move constructor could be any faster or efficient than the copy Copy Constructor. In this case I can't think of anyway to make the Move Constructor any faster/efficient.
Your move code does .. a copy, it should be:
class Test {
std::string name;
std::vector<std::string> friends;
Test() : name{}, friends{} {} // empty string, empty vector.
Test(std::string name, std::vector<std::string> friends) : name{std::move(name)}, friends{std::move(friends)} {}
// ^^^^^^^^^^ ^^^^^^^^
// Copy constructor
Test(const Test &source) : name{source.name}, friends{source.friends} {}
// or simply Test(const Test &) = default;
// Move constructor
Test(Test &&source) noexcept : name{std::move(source.name)}, friends{std::move(source.friends)} {}
// ^^^^^^^^^ ^^^^^^^^
// or simply Test(Test &&) = default;
// Destructor
~Test() = default;
};
Are both of my class definitions correct? And if not, which one/(s) is/aren't correct and why?
Using pointer on std::string/vector is strange but "correct". You miss implementation of operator=
to respect rule of 5.
The version without pointer does copy instead of move, but behave correctly.
Is there a way to make the Move Constructor any faster for the second class Test definition?
Yes, by moving members instead of copy, see above.
Does my thought process match with the correct answer to it? In other words is the Move Constructor limited and won't be any faster compared to the Copy Constructor in the second definition of the Test class?
Both your copy constructor and move constructor does the same thing: a copy, so should be equivalent. the difference is the (wrong) noexcept
. so move will call std::terminate
if exception is throw during the copy.
Upvotes: 1