C++复制拥有POSIX文件描述符的对象的构造函数

Mic*_*eur 3 c++ linux

我需要让C++对象在向量中拥有POSIX文件描述符.我有一个文件路径的向量,我用它来创建我的对象.这是我的代码:

main.cpp中

std::vector<MightyObject> mightyObjects;
std::vector<const char*> paths = {"awesomePath1", "awesomePath2"};
for (std::vector<const char*>::iterator it = paths.begin(); it != paths.end(); ++it)
{
    mightyObjects.emplace_back(MightyObject(*it));
}
Run Code Online (Sandbox Code Playgroud)

MightyObject.cpp

MightyObject::MightyObject(const char* path)
{
   this->fd = open(path, O_RDWR | O_NONBLOCK);
}

MightyObject::~MightyObject()
{
    close(this.fd);
}

MightyObject::MightyObject(const MightyObject& obj)
{
    this->fd = dup(obj.fd);
}

MightyObject& MightyObject::operator=(const MightyObject& other)
{
    this->fd = dup(other.fd);
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

在mightyObjects中,我的对象包含错误的文件描述符......

我究竟做错了什么 ?

use*_*342 7

显示的代码应该包含正确的文件描述符,尽管它会在赋值时泄漏描述符.要修复它,您应该将其更改为:

  • 修复赋值运算符中的泄漏;
  • 处理自我分配;
  • 实现移动构造函数以优化移动(并且因为此类是移动构造的好处的教科书示例);
  • 处理错误.

例如(未经测试):

static int safe_dup(int fd) {
    int copy = dup(fd); 
    if (copy < 0)
        throw std::runtime_error(strerror(errno));
    return copy;
}

MightyObject::MightyObject(const char* path) {
    this->fd = open(path, O_RDWR | O_NONBLOCK);
    if (this->fd == -1)
        throw std::runtime_error(strerror(errno));
}

MightyObject::~MightyObject() {
    if (this->fd != -1)
        close(this->fd);
}

MightyObject::MightyObject(const MightyObject& other) {
    this->fd = safe_dup(other.fd);
}

MightyObject& MightyObject::operator=(const MightyObject& other) {
    if (this != &other) {
        close(this->fd);
        this->fd = safe_dup(other.fd);
    }
    return *this;
}

MightyObject::MightyObject(MightyObject&& other) {
    // "move" file descriptor from OTHER to this: no duping is needed,
    // we just take the descriptor and set the one in OTHER to -1, so
    // it doesn't get closed by OTHER's destructor.
    this->fd = other.fd;
    other.fd = -1;
}

MightyObject& MightyObject::operator=(MightyObject&& other) {
    // move assignment operator
    close(this->fd);
    this->fd = other.fd;
    other.fd = -1;
}
Run Code Online (Sandbox Code Playgroud)

一旦理解了移动语义,就可以通过部署复制和交换习惯来减少运算符之间的代码重复.

请注意,上述内容应理解为编码和理解练习.在生产中,您可能不希望在复制对象时分配新的文件描述符.更好的设计会使文件句柄只移动并实现MightyObjectstd::shared_ptr<Handle>.这将完全避免dup和摆弄复制构造函数,赋值运算符等,因为所有这些都将由处理shared_ptr.