如何移动std::unique_ptr作为构造函数参数

how can i move std::unique_ptr for constructor argument?

本文关键字:ptr 参数 构造函数 unique 移动 std 何移动      更新时间:2023-10-16

我的目标是能够创建一个对象与不同类型的成员对象来自同一个类族;在Java中,它看起来像这样:

public class Interface {
    public void test();
}
public class MyImpl1 implements Interface {
    @Override
    public void test() {System.out.println("I am impl 1");}
}
public class MyImpl2 implements Interface {
    @Override
    public void test() {System.out.println("I am impl 2");}
}
public class A {
    public A(Interface myinter) {
        _myinter = myinter;
    }
    Interface _myinter;
}

这样我就可以创建一个具有不同实现的对象:

A a(new MyImpl1());

A a(new MyImpl2());

(对不起,如果有语法错误在这个拙劣的代码,这只是为了解释我想要的)

所以,在c++中,我想我会用智能指针实现这一点,以受益于RAII。因此,我编写了以下代码:

#include <iostream>
#include <memory>
using namespace std;
struct Interf {
    virtual void test() {cout << "I am Interf" << endl;}
};
struct A {
    A(std::unique_ptr<Interf> e) : _e(std::move(e)) {}
    std::unique_ptr<Interf> _e;
    void test() {_e->test();}
};
struct Impl : public Interf {
    void test() {cout << "I am Impl;" << endl;}
};
int main()
{
    std::unique_ptr<Interf> b(new Impl);
    A a(std::move(b));
    a.test();
    cout << "fine!" << endl;
    return 0;
}
  • 我似乎在工作。但是,这是实现它的正确方法吗?还是有错误,还是更好的实践?

  • 此外,在此代码中,我不确定是否需要使用std::move两次。这是传递unique_ptr到构造器的正确方法吗?

  • 另一件事我不明白的是为什么这段代码不编译,如果我删除_e(std::move(e))从成员初始化列表,并把内部构造函数;谁能解释一下这是怎么回事?

.

struct A {
    A(std::unique_ptr<Interf> e) {
        _e(std::move(e));
    }
    ...
};

有三个std::unique_ptr传递你的Interf:

  • b, main()中的局部变量;
  • e, A的构造函数参数;
  • _e, A实例的成员。

在三个不同的指针上移动Interf实例需要两次连续的std::move()操作(be,然后e_e),这是完全有意义的。

稍微偏离主题:c++ 14鼓励使用std::make_unique。这是c++ 11。

你的代码绝对没问题:)

编辑:

成员变量只在成员初始化列表中初始化。在构造函数体中,_e(std::move(e));意味着调用_eoperator (),就好像它是一个函子一样。

分配给_e应该与_e = std::move(e);一起完成,尽管直接初始化它总是更好。