C ++ Dynamic Array Design

I am developing some classes for dynamic arrays (something like std :: vector). The reason I don't want to use std :: vector is because my C ++ programs are often used as a library called from C / C ++ / Fortran / Delphi, and therefore accept input of arrays as a pointer . For security reasons, std :: vector cannot steal a pointer at build time. My Array1D can work as std :: vector, but can also be created using a pointer. Unfortunately, Visual Studio 2013 seems to bother my design. Before presenting the problem, I need to explain this design.

Here is the layout of my class

template <typename T> class Array1D { private: T* data_; T* size_; // No stored as an int for optimisation purposes bool owner_; public: Array1D(int n) { data_ = new T[n]; size_ = data_ + n; owner_ = true; } Array1D(T* data, int n) { data_ = data; size_ = data + n; owner_ = false; } ... }; 

In most cases, it works like std :: vector, and owner_ is true. You can also build Array1D from a pointer, and this time owner_ is set to false. In this case, some operations, such as resizing, are not allowed (via assert). The copy constructor and assignment for array A are designed as:

  • Array1D (const Array1D & B): A deep copy of B in A. After building A, owns its memory.
  • Array1D (Array1D & B): move operation in all cases. After construction, property status A is B.
  • operator = (const Array1D & B): A deep copy of B in A. If A does not own its memory, there is a statement that A and B are the same size. The assignment does not change the status of owner A.
  • operator = (Array1D & B): move the operation if A and B belong to their memory. Otherwise, we make a deep copy, and the size is checked with assert if A does not own its memory. The assignment does not change the status of owner A.

I applied the same idea to my two-dimensional array whose elements are stored in lowercase order

 template <typename T> class Array2D { private: T* data_; T* size_[2]; bool owner_; public: Array2D(int n, int p) { data_ = new T[n]; size_[0] = data_ + n; size_[1] = data_ + p; owner_ = true; } Array1D(T* data, int n, int p) { data_ = data; size_[0] = data + n; size_[1] = data + p; owner_ = false; } ... Array1D<T> operator()(int i) { Array1D<T> row(data_ + i * nb_columns(), nb_columns()); return row; } ... int nb_columns() const { return static_cast<int>(size_[1] - data_); } }; 

Array1D, returned by the operator () (int i), does not have its own memory and contains a pointer to the i-th line belonging to the Array2D object. It is useful in the following form of code

 sort(Array1D<T>& A); // A function that sorts array in place Array2D<double> matrix(5, 100); // Construct an array of 5 rows and 100 columns ... // Fill the array sort(matrix(3)) // Sort the 4th row 

Those "temporary representations" for strings of 2-dimensional arrays are quite useful, but I prefer to limit them to temporary objects to limit anti-aliasing.

Unfortunately, using Visual Studio 2013, I get the following warning from the IDE to sort the row (matrix (3)): "The options for binding the r-value to l-value are non-standard Microsoft C ++ extensions." I understand that matrix (3) is an object that lives temporarily and modifies it in appearance. But, since this is a "view", its change changes the memory belonging to the matrix, and is useful.

So my questions are:

  • Is this valid C ++? (change of time value)
  • Is there a flaw in this design?

PS: Full code is available on Github .

+6
source share
1 answer

Am I valid C ++? (change of time value)

This is not true. References to a constant cannot be associated with temporary objects: http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

Is there a flaw in this design?

You modify the content that is wrapped in the object. Since you need to have an lvalue value, it is just fixed with an intermediate variable:

 auto m_temp_lvalue = matrix(3); // get the 4th row sort(m_temp_lvalue); // sort the 4th row 

Hope this helps.

0
source

Source: https://habr.com/ru/post/977331/


All Articles