【问题标题】:Constructors and Advanced Exception Throwing C++构造函数和高级异常抛出 C++
【发布时间】:2018-05-21 14:35:30
【问题描述】:

我必须分析这段涉及异常的 C++ 代码,但我不习惯分析代码应该做什么。有几件事我不明白。此外,我没有使用缓冲区数据结构或在 C++ 中引发异常的高级细节方面的经验。

数据结构的最大大小是多少?

  • 也就是说,如果用size_=100做一个Seq_Buffer,有多少个 元素可以存储吗?
  • 我的直觉告诉我,如果你创建一个大小为 100 的东西, 它的最大尺寸为 100,但我无法确定事实。

构造函数可以在 C++ 中抛出异常吗?

  • Seq_Buffer 的构造函数可以抛出异常吗?
  • 假设这是真的,为什么不解释就行了 陈述一个try、catch或throw块?我认为这是获得例外的唯一方法

我试过搜索这两个问题,但我真的很迷茫。感谢您花时间阅读。我已经尝试搜索这两个问题,但我真的很迷茫。感谢您抽出宝贵时间阅读。

Seq_Buffer 类及其构造函数的代码如下:

#ifndef SEQBUFFER_H
#define SEQBUFFER_H

#include <memory>
#include <experimental/optional>

#include "optional.h"

// Exceptions classes
struct full_buffer {};
struct empty_buffer {};

// Sequential buffer for values of type T
template <typename T>
class seq_buffer {
public:
  // Constructs a buffer for n elements
  seq_buffer(int n) :
    size_{n},
    buf_{new item_type[size_]}
  {
  }

  // Default destructor
  ~seq_buffer() = default;

  // Size of buffer
  int size() const noexcept { 
    return size_; 
  }

  // Is buffer empty?
  bool empty() const noexcept { 
    return next_read_ == next_write_; 
  }

  // Is buffer full?
  bool full() const noexcept {
    const int next = next_position(next_write_);
    return next == next_read_;
  }

  // Put element x into buffer with marker last.
  // An empty element signals end of buffer.
  void put(const optional<T> & x);

  // Gets a pair with next element and last indication.
  // Pair is accessed through members first and second
  optional<T> get();

private:
  // Compute next position after p following circular order
  int next_position(int p) const noexcept {
    return p + ((p+1>=size_)?(1-size_):1);
  }

private:
  // Size of buffer
  const int size_;

  using item_type = optional<T>;

  // Unique pointer to buffer of size_ elements.
  std::unique_ptr<item_type[]> buf_;

  // Next position to read
  int next_read_ = 0;

  // Next position to write
  int next_write_ = 0;
};

template <typename T>
void seq_buffer<T>::put(const optional<T> & x)
{
  const int next = next_position(next_write_);
  if (next == next_read_) throw full_buffer{};
  if (!x) {
    buf_[next_write_] = {};
  }
  else {
    buf_[next_write_] = *x;
  }
  next_write_ = next;
}

template <typename T>
optional<T> seq_buffer<T>::get()
{
  if (empty()) throw empty_buffer{};
  auto res = buf_[next_read_];
  next_read_ = next_position(next_read_);
  return res;
}

#endif

【问题讨论】:

  • 好吧,如果你不能通过阅读代码来解决问题,为什么不创建一些测试用例,以便你可以用你的调试器逐步完成它(然后你会及时获得经验)能够在没有它的情况下在精神上做到这一点)你甚至可以尝试自己在构造函数中放入一个 throw 看看会发生什么
  • 构造函数使用new,如果内存不足会抛出bad_alloc。它还构造未知类型的对象item_type。它的构造函数也可能抛出异常。
  • 我认为这是学生的家庭作业。 Raymond Jones,你应该读一本 Stroustrup 的书,这可能是学习 C++ 的最佳方式。
  • 好的,所以有内置的 C++ 异常可以抛出不同的东西,而不需要关键字。我就是这么想的。谢谢!这很有帮助!我还想我可以尝试制作测试用例,我只需要确保我不会忘记可能的情况。
  • @RaymondJones 它比这更笼统:在 C++ 中,函数不需要声明它们可以抛出。几乎任何运算符都可能被某些抛出函数重载。因此,您必须期望 C++ 中的每条语句都能够抛出异常,除非标准另有规定。这包括看似无辜的陈述,如auto a = b;cout &lt;&lt; (a + b);。 (两个例子,三个抛出的机会,你能发现它们吗?)除了通过编译器标志禁用异常支持之外,真的没有办法解决这个问题。

标签: c++ exception constructor throw


【解决方案1】:

是的,我们可以从构造函数中抛出异常。这是处理构造函数失败或类初始化错误的最佳方法。以这个代码为例

class bar
{
public:
  bar()
  {
    std::cout << "bar() called" << std::endl;
  }

  ~bar()
  {
    std::cout << "~bar() called" << std::endl;

  }
};
class foo
{
public:
  foo()
    : b(new bar())
  {
    std::cout << "foo() called" << std::endl;
    throw "throw something";
  }

  ~foo()
  {
    delete b;
    std::cout << "~foo() called" << std::endl;
  }

private:
  bar *b;
};


int main(void)
{
  try {
    std::cout << "heap: new foo" << std::endl;
    foo *f = new foo();
  } catch (const char *e) {
    std::cout << "heap exception: " << e << std::endl;
  }

  try {
    std::cout << "stack: foo" << std::endl;
    foo f;
  } catch (const char *e) {
    std::cout << "stack exception: " << e << std::endl;
  }

  return 0;
}

在这里,您从构造函数本身抛出异常。但是有些情况下,您在构造函数中分配内存(堆)。在这种情况下,在构造函数中抛出异常没有多大用处,因为这会导致内存泄漏。因为如果类初始化失败,那么将不会为类调用析构函数,因为已经抛出异常(假设在析构函数中分配的内存是使用 free 释放的)。所以在构造函数中抛出异常取决于场景或使用case.并非所有情况都受益于在构造函数中抛出异常。

【讨论】:

    猜你喜欢
    • 2014-11-03
    • 1970-01-01
    • 2019-03-11
    • 2023-03-11
    • 2011-11-04
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多