我如何移动 std::unique_ptr 作为构造函数参数?
how can i move std::unique_ptr for constructor argument?
我的目标是能够创建一个对象,其中包含来自同一 class 家族的不同类型的成员对象;在 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 中获益。因此,我写了 this 代码:
#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()
操作(b
到 e
,然后 e
_e
).
稍微偏离主题:C++14 鼓励使用 std::make_unique
。不过这是 C++11。
你的代码绝对没问题:)
编辑:
成员变量仅在成员初始化列表中初始化。在构造函数的主体中,_e(std::move(e));
意味着调用 _e
的 operator ()
就好像它是一个函子。
分配给 _e
应该用 _e = std::move(e);
完成,尽管直接初始化它总是更好。
我的目标是能够创建一个对象,其中包含来自同一 class 家族的不同类型的成员对象;在 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 中获益。因此,我写了 this 代码:
#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()
操作(b
到 e
,然后 e
_e
).
稍微偏离主题:C++14 鼓励使用 std::make_unique
。不过这是 C++11。
你的代码绝对没问题:)
编辑:
成员变量仅在成员初始化列表中初始化。在构造函数的主体中,_e(std::move(e));
意味着调用 _e
的 operator ()
就好像它是一个函子。
分配给 _e
应该用 _e = std::move(e);
完成,尽管直接初始化它总是更好。