English 中文(简体)
Is the move constructor only come in handy if my class has a member that is a raw pointer?
原标题:

I am currently studying the move constructor and the copy constructor. Based on my current understanding, these constructors are used to initialize an object of class X by providing another object of the same class type X. However, there is a distinction between the two: the copy constructor takes a non-temporary object as input, while the move constructor takes a temporary object.

Both the copy and move constructors are particularly useful when a class has a member that is a raw pointer, which may point to memory allocated on the heap.

so what if my class doesn`t have a pointer member just a collection of members of integers and strings and array of doubles for example , how would the copy and move constructor be so important and remove the overhead provided by the default argument constructors? and how would the implementation of the two constructors be done in this case? I am taking about the C++ language

I haven`t tried this case yet. but I tried it with the case of my class has a raw pointer

问题回答

Generally speaking, move constructors and move assignment operators are only needed in two scenarios:

  1. You want your non-POD class to be efficiently movable (e.g. std::vector, std::list, etc);
  2. Your class cannot be copied for some reasons but it needs to be movable (e.g. std::unique_ptr, std::move_only_function, etc).

Both the copy and move constructors are particularly useful when a class has a member that is a raw pointer, which may point to memory allocated on the heap

Not just a memory resource but generally any type of resource/data that doesn t rest in the object representation of a class instance but still belongs to it. It might be a socket, thread, file handle, or something else. An example is the std::string class which may own a buffer of characters that might be located somewhere else in the memory. In other words, the underlying buffer might not be inside a std::string object itself. But it owns the buffer by having a pointer member to it plus a few other members.

Take a look at below example:

#include <string>
#include <utility>
#include <iostream>

class Foo
{
public:
    Foo( const std::string& str, const double val )
    : str_ { str }, val_ { val }
    {}

    // copy ctor
    Foo( const Foo& rhs )
    : str_ { rhs.str_ }, val_ { rhs.val_ }
    {}

    // move ctor
    Foo( Foo&& rhs ) noexcept
    : str_ { std::move( rhs.str_ ) }, val_ { std::exchange( rhs.val_, 0.0 ) }
    {}

    void print_members()
    {
        std::cout << str_ << " " << val_ << "
";
    }

private:
    std::string str_;
    double val_;
};

int main( )
{
    Foo f { "some text", 1.0 };
    Foo f1 { f };
    Foo f2 { std::move( f ) };

    f.print_members( );   // " 0" semantically empty after being *moved from*
    f1.print_members( );  // "some text 1"
    f2.print_members( );  // "some text 1"
}

As can be seen, the creation of f2 through move construction will be more efficient than the creation of f1 through copy construction. Because it simply moves the f.str_ to f2.str_ so it does not copy the underlying buffer of f.str_ to that of f2.str_. In other words, it simply moves the ownership of that buffer of chars to f2. Also, note that the above class doesn t need its copy/move constructors explicitly defined since the compiler can create them implicitly and more efficiently. However, they were implemented for the purpose of demonstration.

what if my class doesn`t have a pointer member just a collection of members of integers and strings and array of doubles

Yes, obviously implementing a move constructor/assignment operator for a POD class (more accurately standard layout) is not going to increase efficiency in most cases since those operations will be equivalent to copying that class. So for instance, if the above Foo class didn t have a std::string member it would be a standard layout type and would not necessarily need move semantics implemented.

Note: The following is not always true

the copy constructor takes a non-temporary object as input, while the move constructor takes a temporary object

The copy constructor can take temporaries (rvalues) too. And the move constructor can take lvalues that were cast to xvalue via std::move as shown in Foo f2 { std::move( f ) }; where f is a non-temporary.

The modern advice for constructors is known as the rule of zero/five.

  1. Ideally, you should write none of the destructor, copy constructor, move constructor, copy assignment and move assignment operators. You either =default then, =delete them, or leave the compiler to write them.

And then the rule of 5:

  1. If you are managing resources, you have to write a destructor. Once you write a destructor, you must write or delete the move constructor, move assignment, copy constructor and copy assignment.

This pair of rules isn t perfect, but covers 99.9% of classes and structs you will right.

The next bit is that you should manage resources in classes whose purpose it is to manage resources. std::vector manages a contiguous buffer of memory, std::unique_ptr manages a uniquely owned object, std::unique_lock manages a lock around a mutex, etc.

That is all they do -- they manage that resource. They have no business logic around the thing they are managing.

If your class uses such resource-management classes to manage resources, then it can use the rule of Zero!

Which then moves your Five special method classes to being a relatively small number of classes. Only when you have a new category of resources do you need to write a new class that has manually written destructors, or copy/move construct/assignment.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签