Why write two () statements

Why do it twice? These two lines, why do you like it so much? Is it enough?

inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; } const inline T& operator() (int row, int col) const { return this->m_data[row*NC + col]; } 

Thank you

  * * 2-DIMENSIONAL ARRAY * * Simulated by 1-dimension array. ******************************************************************************/ #ifndef __2D_ARRAY_H__ #define __2D_ARRAY_H__ #include <stdint.h> #include <stdlib.h> namespace alg { /** * 2D Array definition */ template <typename T=char> class Array2D { private: uint32_t NR; // num of rows uint32_t NC; // num of columns T * m_data; // the place where the array resides. public: /** * construct an array of size [nrow,col] */ Array2D(uint32_t nrow, uint32_t ncol) { NR = nrow; NC = ncol; m_data = new T[nrow*ncol]; } /** * destructor */ ~Array2D() { delete [] m_data; } private: Array2D(const Array2D&); Array2D& operator=(const Array2D&); public: /** * return number of rows of this array */ inline const uint32_t row() const { return NR; } /** * return number of columns of this array */ inline const uint32_t col() const { return NC; } /** * return the value by the given (row, col); */ inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; } const inline T& operator() (int row, int col) const { return this->m_data[row*NC + col]; } inline T* operator[] (int row) { return &(m_data[row * NC]); } inline const T* operator[] (int row) const { return &(m_data[row * NC]); } /** * clear the array by a given value */ void clear(const T & value) { for(uint32_t i=0; i<NR*NC;i++){ m_data[i] = value; } } }; } #endif // 
+6
source share
5 answers

One is const and the other is not.

The difference is that when you have a const reference to Array2D , you are allowed to call member functions labeled const . In this case, this means that the second version, where it must necessarily return a const link to the element that it stores.

If you have a non- const reference, this 2nd version means that you cannot use operator() to make any changes to Array2D .

If you look at standard libraries such as std::vector , you will see that they do the same. You can get iterator from begin() and const_iterator from begin() const .

+10
source

The first, fickle version returns a link that can be modified. If you have a persistent object, you still want to at least read the value, so you need to provide a second persistent version.

+2
source

The two () operators do not match. inline T& operator() (int row, int col); returns a link that allows you to change the return value. const inline T& operator() (int row, int col) const returns a link that forbids changing the return value. Also, if the caller is const alg::Array2D& , it can ONLY use const operator(); . Therefore, for users of the Array2D class to correctly use const objects. It is best to implement both signatures for the () operator.

+2
source

You may have a void make_something (const Array2D<char> &input, Array2D<char> &output) function void make_something (const Array2D<char> &input, Array2D<char> &output) . This function allows you to insert an untouched one, performs some operation with it, and writes the result for output. Reading from input is only possible with the const operator.

0
source
 inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; } 

returns a non-constant data reference in m_data[row * NC + col] , which means that I can do

 auto& ref = obj(x, y); ref = BAD_DATA; 

and your object cannot stop me. The const option protects against this and can be fingerprinted as const, because as a result it has no side effects on the object.

 inline const T& operator() (int row, int col) const { return this->m_data[row*NC + col]; } 

This allows me to extend constness to the outside:

 void myFunc(const Object& obj) /* I'm only going to look */ { const auto& ref = obj(x, y); std::cout << x << ',' << y << " = " << ref << '\n'; } 
0
source

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


All Articles