This question already has answers here:
Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
                                
                                    (3个答案)
                                
                        
                                3年前关闭。
            
                    
我一直在阅读C ++ 11的新move语义,但对我来说不清楚的是,如果使用自定义构造函数会阻止编译器自动向您的类添加move语义。我不知道5的规则是否还包括像下面这样的简单类。

我有以下课程:

class CodeFile
{
private:
    std::vector<Function> functions;
    //std::vector<std::wstring, unsigned long> variables;
    std::vector<std::wstring> lines;
    std::vector<unsigned char> constants;

public:
    std::wstring directory;
    std::wstring fileName;

    void setFilePath(std::wstring filePath);
    bool addFunction(Function function);
    void Run();
    void Finalize();

    CodeFile(std::wstring filePath);
};


最后一行是构造函数。定义此构造函数是否会阻止编译器通过添加move构造函数来优化类?

我应该将类声明为以下内容吗?

class CodeFile
{
private:
    std::vector<Function> functions;
    //std::vector<std::wstring, unsigned long> variables;
    std::vector<std::wstring> lines;
    std::vector<unsigned char> constants;

public:
    std::wstring directory;
    std::wstring fileName;

    void setFilePath(std::wstring filePath);
    bool addFunction(Function function);
    void Run();
    void Finalize();
    static CodeFile fromFile(std::wstring filePath);
};

最佳答案

您无需在这里做任何事情。 C ++将为您编写move构造函数。

但是,只要您对此担心,只需添加

CodeFile(CodeFile &&)=default;
CodeFile(CodeFile const&)=default;
CodeFile& operator=(CodeFile &&)=default;
CodeFile& operator=(CodeFile const&)=default;


并且可能

CodeFile()=default;


这有点烦人,但它也无害,它表示您希望该类是可复制和可移动的(或者您使用的是疯狂的通用代码,并且希望其可复制/可移动性取决于其父级和内容)。

请注意,除非是真正的转换,否则您不应使用非明确的一元参数构造函数。因此,请考虑explicit上的CodeFile(std::wstring)

但是,禁用CodeFile(CodeFile&&)自动写入的任何内容也将禁用CodeFile(CodeFile const&)自动写入。因此,如果发现不能再复制它,也不能再移动它(除非您手动编写了CodeFile(CodeFile const&),这当然会禁用CodeFile(CodeFile&&)而不禁用自身)。

为了诊断这样的事情,我通常写noisy

struct noisy {
  noisy(){std::cout << "ctor()\n";}
  noisy(noisy&&){std::cout << "ctor(&&)\n";}
  noisy(noisy const&){std::cout << "ctor(c&)\n";}
  void operator=(noisy&&){std::cout << "asgn(&&)\n";}
  void operator=(noisy const&){std::cout << "asgn(c&)\n";}
  ~noisy() {std::cout << "~\n"; }
};


除了发出声音外什么也没做。

然后我们写一个玩具类型:

struct Foo {
  Foo (int) {}
  noisy _;
};


与我们关心的属性。

一点测试:

Foo f(7);
f = Foo(3);
Foo f2=std::move(f);


证明move构造函数很好。通过编写Foo,只有默认构造函数已从Foo(int)中删除​​。

live example

10-07 14:17