如何使用带构造函数的initializer-list进行异常处理?

时间:2018-01-03 18:54:24

标签: c++ exception-handling stdinitializerlist

我曾经通过Constructor使用initialization list,一切顺利。但是现在我的课堂上需要一些exception handling

以下是一些示例代码:

1-无异常处理

class CVector{
    public:
        CVector(const int);
    protected:
        int* pInt;
        int size;
};

CVector::CVector(const int sz) :
    pInt{ new int[sz]}, size{ sz}{

}

上面的构造函数不检查是否传递了无效的大小,或new失败...

现在我编辑了构造函数来处理异常:

2-有异常处理:

CVector::CVector(const int sz){
    size = sz;
    if(size <=0 )
        throw; // some exception object

    pInt = new int[sz];
    if(nullptr == pInt)
        throw; // some memory exception
}
  • 现在的问题:它们是独家的吗? - 我的意思是如何通过Constructor将异常处理与initialization-list混合使用?

2 个答案:

答案 0 :(得分:2)

首先,您不清楚是否有意让CVector承担拥有整数动态的责任。你可能会这样做。

几乎没有失败,您将希望程序中的每个类最多管理一个动态资源(例如分配的内存)。这是因为当有多个资源时,作业变得繁重。

在您的情况下,资源是int数组。因此,让我们向CVector负责,让我们使用unique_ptr来管理这一责任:

#include <memory>
#include <cstddef>
#include <algorithm>

struct CVector
{
    CVector(std::size_t initial_size)
    : data_ { std::make_unique<int[]>(initial_size) }
    , size_ { initial_size }
    {
    }

    // we will probably want the vector to be copyable
    CVector(CVector const& other)
    : data_ { std::make_unique<int[]>(other.size_) }
    , size_ { other.size_ }
    {
        auto first = other.data_.get();
        auto last = first + other.size_;
        std::copy(first, last, data_.get());
    }

    // move consruction is defaultable because it is enabled for
    // unique_ptr

    CVector(CVector&&) = default;

    // assignment

    CVector& operator=(CVector const& other)
    {
        auto temp = other;
        swap(temp);
        return *this;
    }

    CVector& operator=(CVector&& other) = default;

    // no need for a destructor. unique_ptr takes care of it

    void swap(CVector& other) noexcept
    {
        using std::swap;
        swap(data_, other.data_);
        swap(size_, other.size_);
    }

private:
    // defer memory ownership to a class built for the job.
    std::unique_ptr<int[]> data_;
    std::size_t size_;
};

答案 1 :(得分:1)

1)提取大小验证检查到一个单独的静态方法(最有可能它将被重用); 2)不再需要检查new返回的值,如果失败则应抛出std::bad_alloc异常。所以你的代码可以变成这样:

class CVector{
public:
    CVector(const int);
    static int Validate_Size(int const size);
protected:
    int * m_pInt;
    int m_size;
};

int CVector::Validate_Size(int const size)
{
   if(size <= 0)
   {
      throw std::invalid_argument{};
   }
   return(size);
}

CVector::CVector(const int size)
:  m_pInt{new int[Validate_Size(size)]}
,  m_size{size}
{}