我有一节课,说Foo
,定义如下:
class Foo {
public:
Foo(int i) {
valid = false;
char devname[] = "/dev/device0";
sprintf(devname, "/dev/device%d", i);
fd = open(devname, O_RDWR);
if (fd > 0) {
valid = true;
}
~Foo() {
if (valid) {
close(fd);
}
}
bool valid;
private:
int fd;
};
我还有一个类(class),比如说Bar
,定义如下:
class Bar {
public:
Bar() {
for (int i = 0; i < 4; i++) {
Foo foo(i);
if (foo.valid) {
vector_of_foos.push_back(foo);
}
}
}
std::vector<Foo> vector_of_foos;
};
问题在于 push_back
复制 Foo 对象,复制 fd
属性(property)。然后是原始 Foo
的析构函数对象被调用,它关闭了 fd
的文件指向,渲染fd
无效。
不幸的是我不能使用emplace_back
因为我需要实例化我的 Foo
对象 before 添加到 vector_of_foos
vector ,以便我可以检查 valid
属性(property)。
我也尝试过使用 std::move
但这仍然调用原始 Foo
的析构函数对象一旦超出范围就会关闭文件。
管理这样的资源的推荐方法是什么?我应该使用智能指针数组吗?应该是我的vector_of_foos
改为 std::vector<Foo *>
我在其中维护指向 Foo
的指针 vector 我动态分配哪个?
最佳答案
Foo
需要复制构造函数和复制赋值运算符,因此它可以 dup()
复制源对象的 fd
(或者,您需要删除
它们,这样Foo
对象根本无法复制,只能移动)。
在实现移动语义时,将 fd
值从移出对象移动到移入对象后,需要更新移出对象,使其 fd
不再引用有效的文件描述符。只需将它设置为 -1,这是 open()
和 dup()
返回的错误。
您根本不需要您的有效
成员。如果它与您的 fd
不同步,这就是等待发生的错误来源。
尝试更像这样的东西:
class Foo {
public:
Foo(int i) {
std::string devname = "/dev/device" + std::to_string(i);
fd = open(devname.c_str(), O_RDWR);
}
Foo(const Foo &src) {
fd = dup(src.fd);
}
// or: Foo(const Foo &) = delete;
Foo(Foo &&src) : fd(-1) {
src.swap(*this);
}
~Foo() {
if (fd != -1) {
close(fd);
}
}
bool valid() const {
return (fd != -1);
}
Foo& operator=(Foo rhs) {
rhs.swap(*this);
return *this;
}
// optional: Foo& operator=(const Foo &) = delete;
void swap(Foo &other) {
std::swap(fd, other.fd);
}
private:
int fd;
};
关于c++ - 使用文件描述符移动对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56369138/