I have a container class like the following. As you can see that all the resources that the class use is allocated statically. There are no dynamically allocated resources in the class. Does such a class need a move constructor or move assignment operator?
template<class T, std::size_t SIZE>
class Stack{
static_assert(SIZE != 0, "Stack capacity cannot be zero!");
public:
/*** Constructors and Destructor ***/
Stack() = default; // Default constructor
Stack(const Stack& copyStack); // Copy constructor
~Stack(); // Destructor
/*** Member Methods ***/
/* .... */
void swap(Stack& swapStack);
private:
/*** Members ***/
std::size_t idxTop{0}; // Index after the top element
T data[SIZE]; // Contained data
};
For the ones who would like to try it out with the actual implementation:
A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying.
No move constructor is automatically generated.
A move constructor allows the resources owned by an rvalue object to be moved into an lvalue without creating its copy. An rvalue is an expression that does not have any memory address, and an lvalue is an expression with a memory address.
If any constructor is being called, it means a new object is being created in memory. So, the only difference between a copy constructor and a move constructor is whether the source object that is passed to the constructor will have its member fields copied or moved into the new object.
Here's the thing. Your class isn't movable, because it doesn't have dynamically allocated resources. But the resources it contains might. A T
, for instance, might be a std::vector
in some instantiation. That can surely be moved, so you have to make sure that by providing a copy constructor (you forgot to = default;
it btw), the compiler doesn't accidentally disable the default move constructor.
Now, you should be careful about the default move constructor in your case. The problem is that you have an array as a member, and the default move constructor just moves the elements of the array one by one.
Except what happens when the move constructor of one of them throws? You end up with half of the elements moved, and some still in the old array because an exception was thrown. That's no good. Take a look at std::move_if_noexcept
and perhaps try implementing the move constructor to fix this.
What exactly do you mean by need? I guess that you mean whether you need to write them for you class to stay moveable.
If you have an example like this:
#include <cstdint>
#include <utility>
class Foo
{
private:
std::size_t idxTop{0};
int data[4];
};
int main()
{
Foo f = Foo(); // Default ctor
Foo x = Foo(f); // Copy ctor
x = f; // Copy assignment
x = std::move(f); // Move assignment
Foo y = std::move(f); // Move ctor
}
The compiler will add
inline constexpr Foo() noexcept = default;
inline constexpr Foo(const Foo &) noexcept = default;
inline constexpr Foo(Foo &&) noexcept = default;
inline constexpr Foo & operator=(const Foo &) noexcept = default;
inline constexpr Foo & operator=(Foo &&) noexcept = default;
to the class's definition. I.e the class can be copied, moved freely as is shown in the main.
But - that's maybe what prompted your question - if you write a custom {copy con,des}structor for a class as you have done, the compiler will not put the defaulted definitions there. Why? Because by writing custom ones, you sent a signal that your class in some way special and default implementations would most likely not do the right thing.
So, your class is not moveable but remains copyable and copies will be used instead of move operations when required - e.g. the last two lines in my example.
I would suggest that whenever you customize one of those 5 functions, you define all of them, use default
or delete
if they suffice.
You can find more information about the default rules in the rule of three/five/zero.
No, your class does not need a move-ctor or move-assignment-operator.
You can't move static arrays, you can only copy their content. So a potential move-ctor would do the same as the copy-ctor. The same goes for assignment operators.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With