如何使用Move-emantics从类构造函数中重新分配资源?

发布于 2025-02-01 05:52:49 字数 839 浏览 1 评论 0原文

为了使我能够阅读一个二进制文件,我已经完成了此类。我想不复制我试图使用移动语义的临时性。但是此代码产生“访问违规错误”。

#include <fstream>
#include <iostream>

class myClass
{
public:
    std::istream& myStream;
    static myClass create(const char* path);
    myClass(myClass&&) noexcept = default;
    myClass(std::istream& input);
    myClass() = default;
};

myClass myClass::create(const char* path)
{
    std::ifstream input{ path, std::ios::binary | std::ios::in };
    if (!input.is_open()) throw std::runtime_error("Error - couldn't open file");
    return std::move(myClass(input));
}

myClass::myClass(std::istream& input) :
    myStream(input)
{

}
int main()
{
    const char* path = R"(file.bin)";
    myClass cr{myClass::create(path)};

    for (int i = 0; i < 10; ++i)
        cr.myStream.seekg(i);

    return 0;
}

To enable me to read a binary file I have made this class. I would like to not copy a temporary for which I am trying to use move semantics. But this code produces "access violation error".

#include <fstream>
#include <iostream>

class myClass
{
public:
    std::istream& myStream;
    static myClass create(const char* path);
    myClass(myClass&&) noexcept = default;
    myClass(std::istream& input);
    myClass() = default;
};

myClass myClass::create(const char* path)
{
    std::ifstream input{ path, std::ios::binary | std::ios::in };
    if (!input.is_open()) throw std::runtime_error("Error - couldn't open file");
    return std::move(myClass(input));
}

myClass::myClass(std::istream& input) :
    myStream(input)
{

}
int main()
{
    const char* path = R"(file.bin)";
    myClass cr{myClass::create(path)};

    for (int i = 0; i < 10; ++i)
        cr.myStream.seekg(i);

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半寸时光 2025-02-08 05:52:49

临时销毁后,您将进入流。您需要将流存储在myClass对象中:

#include <fstream>
#include <iostream>

class myClass
{
public:
    std::istream& myStream;
    static myClass create(const char* path);
    myClass(myClass&& other) noexcept;
    myClass(std::istream& input);
    myClass() = default;
};

myClass myClass::create(const char* path)
{
    std::ifstream input{ path, std::ios::binary | std::ios::in };
    if (!input.is_open()) throw std::runtime_error("Error - couldn't open file");
    return std::move(myClass(input));
}

myClass::myClass(myClass&& other) noexcept :
    myStream(other.myStream)
    {
    other.myStream = std::cin;
}

myClass::myClass(std::istream& input) :
    myStream(input)
{

}
int main()
{
    const char* path = R"(file.bin)";
    myClass cr{myClass::create(path)};

    for (int i = 0; i < 10; ++i)
        cr.myStream.seekg(i);

    return 0;
}

You are accessing the stream after the temporary has been destroyed. You need to store the stream in the myClass object:

#include <fstream>
#include <iostream>

class myClass
{
public:
    std::istream& myStream;
    static myClass create(const char* path);
    myClass(myClass&& other) noexcept;
    myClass(std::istream& input);
    myClass() = default;
};

myClass myClass::create(const char* path)
{
    std::ifstream input{ path, std::ios::binary | std::ios::in };
    if (!input.is_open()) throw std::runtime_error("Error - couldn't open file");
    return std::move(myClass(input));
}

myClass::myClass(myClass&& other) noexcept :
    myStream(other.myStream)
    {
    other.myStream = std::cin;
}

myClass::myClass(std::istream& input) :
    myStream(input)
{

}
int main()
{
    const char* path = R"(file.bin)";
    myClass cr{myClass::create(path)};

    for (int i = 0; i < 10; ++i)
        cr.myStream.seekg(i);

    return 0;
}
醉酒的小男人 2025-02-08 05:52:49

问题是input in myClass :: create()的寿命。正如Jensenmckenzie所提到的那样,它将在该功能的末尾被破坏,因此将传递给返回的myClass对象的 Reference 将是一个悬空的参考。 函数的唯一方法是存储一个具体

class myClass
{
    std::ifstream myStream;
    ...
};

保持myClass :: create() 另一个std :: ifstream要传递给构造函数,它必须作为R值参考:

myClass::myClass(std::ifstream&& input): myStream(std::move(input)) {}

然后您可以编写create> create()函数这样的功能:

myClass myClass::create(const char* path)
{
    std::ifstream input{ path, std::ios::binary | std::ios::in };
    if (!input.is_open()) throw std::runtime_error("Error - couldn't open file");
    return std::move(input);
}

请注意,您还可以写一个将路径名作为参数的构造函数:

myClass::myClass(const char *path):
        myStream(path, std::ios::binary | std::ios::in)
{
    if (!input.is_open())
        throw std::runtime_error("Error - couldn't open file");
}

然后您可以用main()而写下此构造函数:

const char *path = ...;
myClass cr(path);

这根本不需要移动。

The problem is the lifetime of input in myClass::create(). As JensenMcKenzie mentioned, it will be destroyed at the end of that function, and therefore the reference passed to the returned myClass object will be a dangling reference. The only way to keep the myClass::create() function would be to store a concrete std::ifstream object inside myClass:

class myClass
{
    std::ifstream myStream;
    ...
};

To allow another std::ifstream to be passed to the constructor, it has to be as an r-value reference:

myClass::myClass(std::ifstream&& input): myStream(std::move(input)) {}

And then you can write the create() function like so:

myClass myClass::create(const char* path)
{
    std::ifstream input{ path, std::ios::binary | std::ios::in };
    if (!input.is_open()) throw std::runtime_error("Error - couldn't open file");
    return std::move(input);
}

Note that you could also just have written a constructor that takes a pathname as an argument:

myClass::myClass(const char *path):
        myStream(path, std::ios::binary | std::ios::in)
{
    if (!input.is_open())
        throw std::runtime_error("Error - couldn't open file");
}

And then you could have written this in main() instead:

const char *path = ...;
myClass cr(path);

This way no moves are necessary at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文