首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在构造过程中抛出bad_alloc时实现正确的堆栈展开和raii

如何在构造过程中抛出bad_alloc时实现正确的堆栈展开和raii
EN

Stack Overflow用户
提问于 2017-05-19 15:39:05
回答 2查看 119关注 0票数 1

所以我正在设计一个处理大量内存的类,如果在它的构造函数的内存分配过程中出现问题,我想确保它能正确地解开。

下面是我得到的信息:

代码语言:javascript
运行
复制
class foo{
public:
    foo(): var1(nullptr), var2(nullptr){
        try{
        var1 = new int(1);
        var2 = new int(2);
        }
        catch(std::exception &e){
            delete var1;
            delete var2;
            return;
        }
    //Some other things involving these variables
}

如果我只想在构造器中后面的代码因为bad_alloc异常而导致错误之前停止构造这个对象,那么在catch块中返回这个值对吗?或者catch块在终止时只是取消构造函数?我是不是把整件事搞得太复杂了?

EN

回答 2

Stack Overflow用户

发布于 2017-05-19 15:49:06

我想确保如果在它的构造函数的内存分配过程中出现问题,它会正确地展开。

然后,您必须使您的代码符合“一个类控制一个资源或做一个工作”的思想。

代码语言:javascript
运行
复制
#include <memory>

// foo has one job - to manage fooness. 
// It no longer manages memory resources

class foo
{
public:
    foo()
    : var1(new int(1))
    , var2(new int(2))
    {
    }

    std::unique_ptr<int> var1;   // unique_ptr only manages a resource
    std::unique_ptr<int> var2;   // unique_ptr only manages a resource
};

其他正确的初始化形式:

代码语言:javascript
运行
复制
#include <memory>

// foo has one job - to manage fooness. 
// It no longer manages memory resources

class foo
{
public:
    foo()
    : var1(std::make_unique<int>(1))
    , var2(std::make_unique<int>(2))
    {
    }

    std::unique_ptr<int> var1;   // unique_ptr only manages a resource
    std::unique_ptr<int> var2;   // unique_ptr only manages a resource
};

默认值:

代码语言:javascript
运行
复制
#include <memory>

// foo has one job - to manage fooness. 
// It no longer manages memory resources

class foo
{
public:
    // default constructor now implicit

    std::unique_ptr<int> var1 = std::make_unique<int>(1);   // unique_ptr only manages a resource
    std::unique_ptr<int> var2 = std::make_unique<int>(2);   // unique_ptr only manages a resource
};

正确,但习惯用法是令人不快的-冗余初始化:

代码语言:javascript
运行
复制
#include <memory>

// foo has one job - to manage fooness. 
// It no longer manages memory resources

class foo
{
public:
    foo()
    : var1(nullptr)
    , var2(nullptr)
    {
        var1 = std::make_unique<int>(1);
        var2 = std::make_unique<int>(2);
    }

    std::unique_ptr<int> var1;   // unique_ptr only manages a resource
    std::unique_ptr<int> var2;   // unique_ptr only manages a resource
};

这里有一种不用组合就能做到的方法。注意所有额外的复杂性,而不会获得任何收益:

代码语言:javascript
运行
复制
#include <memory>

// foo now has two jobs - to manage fooness, and to manage resources. 
// This adds un-necessary complication, bugs and maintenance overhead

class foo
{
public:
    foo()
    : var1(nullptr)
    , var2(nullptr)
    {
        var1 = new int(1);
        var2 = new int(2);
    }

    foo(const foo& other)
    : var1(nullptr)
    , var2(nullptr)
    {
        if (other.var1) {
            var1 = new int(*(other.var1));
        }

        if (other.var2) {
            var2 = new int(*(other.var2));
        }
    }

    foo(foo&& other) noexcept
    : var1(other.var1)
    , var2(other.var2)
    {
        other.var1 = nullptr;
        other.var2 = nullptr;
    }

    foo& operator=(const foo& other)
    {
        foo tmp(other);
        std::swap(var1, tmp.var1);
        std::swap(var2, tmp.var2);
        return *this;
    }

    foo& operator=(foo&& other) noexcept
    {
        foo tmp(std::move(other));
        std::swap(var1, tmp.var1);
        std::swap(var2, tmp.var2);
        return *this;
    }

    ~foo() noexcept
    {
        delete var1;
        delete var2;
    }

    int* var1;   // doesn't manage anything
    int* var2;   // doesn't manage anything
};
票数 0
EN

Stack Overflow用户

发布于 2017-05-19 15:51:30

您应该检查一下智能指针:std::unique_ptr (在本例中很有用)和std::shared_ptr/std::weak_ptr (对于您的示例来说,类型不是正确的,但很好知道)。

只要你没有重新实现某种类型的智能指针,使用它们而不是动态分配,它将为你省去一些麻烦(即使你的例子是正确的,不会泄漏,只要析构函数是正确的)。

您应该抛出一个异常,而不是返回:应该通知调用者构造失败(如果分配失败意味着构造函数失败)。RAII意味着对象永远不应该处于无效状态。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44064194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档