0

I have to analyze this C++ code which involves exceptions, but I’m not used to analyzing what code is supposed to do. There’s several things about it I don’t understand. Additionally, I don’t have experience with a buffer data structure or advanced details of throwing exceptions in C++.

What is the max size of the data structure?

  • That is to say, if a Seq_Buffer is made with size_ = 100, how many elements can be stored?
  • My intuition tells me that if you create something with size 100, it’s max size will be 100, but I can’t be sure with facts.

Constructors can throw exceptions in c++?

  • Can the constructor for Seq_Buffer throw an exception?
  • Assuming this is true, why does that work without explicating stating a try, catch, or throw block? I thought that was the only way to get exceptions

I’ve tried searching for these two questions, but I’m really quite lost. Thank you for taking the time to read.I’ve tried searching for these two questions, but I’m really quite lost. Thank you for taking the time to read.

The code for the Seq_Buffer class with its constructor is below:

#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
5
  • 1
    Well, if you can't work it out reading the code, why not create some test cases so that you can step through it with your debugger (and then in time you'll get experience to be able to do this mentally without it) You can even then try putting in a throw in the constructor yourself and see what happens Commented Dec 7, 2017 at 13:11
  • 1
    The constructor uses new which can throw bad_alloc if out of memory. It also constructs objects of the unknown type item_type. Its constructor could possibly also throw an exception. Commented Dec 7, 2017 at 13:18
  • I think this is a student home work. Raymond Jones, you should read one of the Stroustrup books, this is probably the best way to learn C++. Commented Dec 7, 2017 at 13:24
  • Okay, so there's built-in C++ exceptions that can throw different things, without needing keywords. That's what I was thinking. And thank you! This helps a lot! I also suppose I could try making test cases, I just have to make sure I don't forget a possible situation. Commented Dec 7, 2017 at 13:34
  • @RaymondJones It's more general than that: In C++, functions do not need to declare that they may throw. And pretty much any operator may be overloaded by some throwing function. As such, you must expect each and every statement in C++ to be able to throw, unless specified otherwise by the standard. This includes seemingly innocent statements like auto a = b; and cout << (a + b);. (Two examples, three opportunities to throw, can you spot them all?) There's really no way around that, short of disabling exception support via compiler flags. Commented Dec 7, 2017 at 13:46

1 Answer 1

1

Yes we can throw exceptions from constructors.It is the best way of dealing with constructor failures or class initialization error.Take this code example

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;
}

Here you are throwing exception from the constructor itself.But there are situations where you allocate memory(heap) in the constructor.In those situation it is not much useful to throw exception in the constructor as this will lead to memory leak.Because if the class fails to initialize then there will be no destructor called for the class as there is already exception thrown(assuming that in the destructor the allocated memory is freed using free).So throwing exception in constructor depends on the scenario or the use case.Not every situation benefits from throwing exception in the constructor.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.