I have a private member of class called mat[3][3], and I want to be able to access this 3x3 array outside of my class (only read it, not change). Is it possible to write accessor method that returns pointer to my array? How can I do this? Please provide code sample.
Here is my class:
class myClass {
private:
int mat[3][3];
public:
return_value get_mat(void);
};
I know I can use something like
int get_mat(int i, int j);
to access every int inside the array one by one, but wouldn't it be inefficient to call the accessor for every member of the array?
Is it possible to write accessor method that returns pointer to my array? How can I do this?
Here's one way:
#include <iostream>
#include <algorithm>
#include <iterator>
class myClass {
public:
const int* operator[](size_t i) const {
return mat[i];
}
int* operator[](size_t i) {
return mat[i];
}
int* get_mat() {
return &mat[0][0];
}
const int* get_mat() const {
return &mat[0][0];
}
private:
int mat[3][3];
};
int main()
{
using namespace std;
myClass m;
m[0][1] = 6;
cout << m[0][1] << endl;
fill(m.get_mat(), m.get_mat() + 9, 11);
copy(m.get_mat(), m.get_mat() + 9, ostream_iterator<int>(cout, ", "));
cout << endl;
return 0;
}
but wouldn't it be inefficient to call the accessor for every member of the array?
Happily, no. in a release build your compiler will optimise all that away much better than you can probably imagine.
Express your intent elegantly. Allow the compiler to write optimal code for you (it will).
expected output:
6
11, 11, 11, 11, 11, 11, 11, 11, 11,
As we start to flesh out the matrix class, we'd probably want to start building in some safety measures against buffer overruns (this code probably requires c++14)...
#include <iostream>
#include <algorithm>
#include <iterator>
#include <functional>
#include <random>
#include <cassert>
template<class T, size_t N>
struct safe_array_ref
{
constexpr safe_array_ref(T* data) : _data(data) {}
constexpr T& operator[](size_t i) const noexcept {
assert(i < N);
return _data[i];
}
constexpr T* begin() const {
return _data;
}
constexpr T* end() const {
return _data + N;
}
constexpr size_t size() const {
return N;
}
private:
T* _data;
};
class myClass {
public:
auto operator[](size_t i) const {
// provide some degree of safety
assert(i < extent_1);
return safe_array_ref<const int, extent_2>(mat[i]);
}
auto operator[](size_t i) {
// provide some degree of safety
assert(i < extent_1);
return safe_array_ref<int, extent_2>(mat[i]);
}
int* get_mat() {
return &mat[0][0];
}
const int* get_mat() const {
return &mat[0][0];
}
const int* begin() const {
return get_mat();
}
const int* end() const {
return get_mat() + total_extent;
}
int* begin() {
return get_mat();
}
int* end() {
return get_mat() + total_extent;
}
constexpr size_t size() const {
return total_extent;
}
private:
int mat[3][3];
public:
constexpr static size_t extent_1 = std::extent<decltype(mat)>::value;
constexpr static size_t extent_2 = std::extent<std::remove_extent_t<decltype(mat)>>::value;
constexpr static size_t total_extent = extent_1 * extent_2;
};
int main()
{
using namespace std;
myClass m;
m[0][1] = 6;
cout << m[0][1] << endl;
generate(m.begin(),
m.end(),
bind(uniform_int_distribution<int>(0,99),
default_random_engine(random_device()())));
// copy the whole matrix to stdout
copy(m.begin(),
m.end(),
ostream_iterator<int>(cout, ", "));
cout << endl;
// copy one row/column of the matrix to stdout
copy(m[1].begin(),
m[1].end(),
ostream_iterator<int>(cout, ", "));
cout << endl;
return 0;
}
sample output:
6
76, 6, 39, 68, 40, 77, 28, 28, 76,
68, 40, 77,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With