-1

What's the best course of action in C++ to take in the following situation?

My class has some double pointer as a private member:

class A
{
private:
    int** data;
    //...//
public:
    int** get_data () const { return data; };
    //...//
}

And sometimes I'd like to check the values inside this pointer and change them. And there's some get function get_data for this purpose:

A* obj = new A();
//...//
int** data_from_A = obj->get_data();
// some manipulations with data_from_A pointer

But what if I want to be confident that nothing won't change it in the further usage? How is it better to get only the "read access" to the data pointer?

Of course, we can make the data pointer public, but in this case it can be changed from the outside, that is unacceptable...

Thanks!

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
Igor Poletaev
  • 339
  • 1
  • 9
  • 4
    Can you elaborate? You said *"I'd like to check the values inside this pointer and **change** them"*, but *"I want to be confident that nothing **won't change** it"*? – HolyBlackCat Jul 03 '17 at 14:51
  • 1
    Also, why so many pointers? – Rakete1111 Jul 03 '17 at 14:52
  • I meant the case when I do not need to do any manipulations with data outside the class, but only need to look through the data inside the pointer. – Igor Poletaev Jul 03 '17 at 14:54
  • 3
    So you don't need to change the pointed values outside of the class? Then you could just return `const int *const *` from `data()`. – HolyBlackCat Jul 03 '17 at 14:55
  • Yes, I can write `const int* const* get_data () const { return data; };`. But the question is: is there any other way to do this? – Igor Poletaev Jul 03 '17 at 14:59
  • @IgorPoletaev Why do you need another way? – Rakete1111 Jul 03 '17 at 15:01
  • Just such a syntax is a little confusing. For example, if I use a triple pointer, then I have to write 3 const qualifiers, and so on. If there is no other more elegant way, then ok.. Anyway, thanks for your comments! – Igor Poletaev Jul 03 '17 at 15:04
  • 3
    @IgorPoletaev Then just don't use pointers :) – Rakete1111 Jul 03 '17 at 15:05
  • Provide some context, not sure what you want to do why. Especially since the const pointer is not what you want. Other ways could include things like "ditch the pointer to 2d-array which it probably is, use std::vector and write it as `const vector >& get_data() const;`" and "write a getter for a single position, `const int& get_data(cont size_t i, const size_t j) const;`" – Aziuth Jul 03 '17 at 15:06
  • @IgorPoletaev You may be interested in the concept of [const methods](https://stackoverflow.com/questions/751681/meaning-of-const-last-in-a-c-method-declaration) and [const correctness](https://isocpp.org/wiki/faq/const-correctness). – François Andrieux Jul 03 '17 at 15:06
  • Maybe turn it on it's head and send a method to the class to update with a predicate? – doctorlove Jul 03 '17 at 15:08
  • @Rakete1111, unfortunately, it's such situation when it's better to use pointers because of some other reasons associated with the task that I decide. – Igor Poletaev Jul 03 '17 at 15:08
  • @François Andrieux, thanks for links! – Igor Poletaev Jul 03 '17 at 15:10
  • 1
    The only valid reason to expose something like a raw array to the outside is that you already have code which requires such an input and would be tedious to rewrite, aka a solver written by C programmers. If not, go with std::vector or std::array, or if you want to symbolize 2d fields in particular, write a base class for those. In C++, raw pointers and especially pointer arithmetics should only exist buried deep in some class that needs them for super-optimized high performance computing. – Aziuth Jul 03 '17 at 15:14
  • @Aziuth, thank you. With vectors, of course, everything is simpler. Apparently it's really better to replace all pointers to vectors .. – Igor Poletaev Jul 03 '17 at 15:15
  • Note that I edited my answer and added how to retrieve the data. If you are not used to work with vectors, you might make the basic mistake of copying data without need. – Aziuth Jul 03 '17 at 15:26

2 Answers2

1

The answer is to make "data" private and make the function which sets it up a "friend". Then the member is protected from access, except within your special function.

However friend functions are usually a sign of poor design, so you will probably want to look at refactoring to eliminate the need for this.

Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18
  • How does this fulfil his requirement of, quote, *"But what if I want to be confident that nothing won't change it in the further usage?"*? – Aziuth Jul 03 '17 at 15:15
  • Nothing else can change it, except that one "friend" function. Unless you call the friend function incorrectly for a second time you are safe. – Malcolm McLean Jul 03 '17 at 15:24
1

In C++, raw pointers, and especially pointer arithmetics, should only be used buried deep deep within a class that utilizes them for high performance computing.

The only reason to give something like a pointer to an array to the outside is that you use some other code that would be tedious to rewrite, like a highly optimized solver written by somebody who is used to writing C style code (with the solver actually being in C maybe).

If not, go with a class from the standard library, like std::vector (dynamic), std::array (static) or std::list (linked).

This would transform your code to something like

private:
    vector<vector<int> > data;

public:
    const vector<vector<int> >& get_data() const { return data; }

Simple as that, one const totally suffices, none more required for sub-vectors as it would be with a raw array.

Another way would be to go with

const int& get_data(const size_t i, const size_t j) const { return data[i][j]; }

which would work even with your current code.

For the vector, remember that if you want to use it for a while, then you have to get it with

const vector<vector<int> >& data = myClass.get_data();

and not with either of those

vector<vector<int> >& data = myClass.get_data(); //compile error
vector<vector<int> > data = myClass.get_data(); //works but unnecessarily copies the data
Aziuth
  • 3,652
  • 3
  • 18
  • 36
  • It's good solution for small data size inside this pointer. But in my situation, the very large matrix is inside the pointer. Therefore, I think, the more simpler data types - the more effective computations are. – Igor Poletaev Jul 03 '17 at 15:29
  • std::vector is essentially a wrapper for a (dynamic) array. In any case, it's data is stored consecutive in memory. Most optimizations, like OpenMP parallelization, work as fine as on raw arrays. That said, there is always the possibility of a new wrapper class... although in such a case, if you really want to optimize, you have to be deep in this topic and invest some time, especially in testing it in vivo. Usually, you'd trust in the tools from std to be better optimized than what you would achieve by yourself. – Aziuth Jul 03 '17 at 15:51
  • @IgorPoletaev: _"I think, the more simpler data types - the more effective computations are"_ Nope. – Lightness Races in Orbit Jul 03 '17 at 16:05