0

Recently I encounter the following code, it is an excerpt from tutorial of open-source package AMReX text

Array4<Real> const& a = fab1.array();
    Dim3 lo = lbound(a);
    Dim3 hi = ubound(a);
    int nc = a.nComp();
    for(int n=0; n<nc; n++){
        for(int i=lo.x; i<=hi.x; i++){
            for(int j=lo.y; j<=hi.y; j++){
                for(int k=lo.z; k<=hi.z; k++){
                    a(i, j, k, n) = 2.0;
                }
            }
        }
    }

Array4 is a class with template which stores the data of grid points, like matrix, tensor etc. I am wondering why here variable "a" as a reference referring to a constant object can be used to modify the object's data. What are the reasons behind it? Thanks!

The tutorial says that "const means the Array4 object itself cannot be modified to point to other data". So why Array4 object can be modified here?

2
  • 5
    In my humble opinion, the class is poorly designed. Its operator() is marked const but returns a non-const reference. This violates the principle of least astonishment. That phrase in the tutorial, "cannot point to other data", doesn't make sense - the class is not pointer-like, it stores its own data and cannot be made to "point to other data", const or no const. Commented Jul 10 at 4:21
  • @IgorTandetnik I wonder if this is something that originated in .NET (or with a primarily .NET developer); C# and VB really don't have anything that works like C++ const, and the sense of const here functions rather like a readonly object variable in C# or VB.
    – Craig
    Commented Jul 10 at 15:24

2 Answers 2

1

why Array4 object can be modified here?

Because the overloaded Array4::operator() returns a non-const lvalue ref which can be used to modify the referred to object from outside(by the caller).

template <class U=T, std::enable_if_t<!std::is_void_v<U>,int> = 0>
//see the RETURN TYPE IS NON-CONST LVALUE REF        
U& operator() (int i, int j, int k) const noexcept {
 //other code here
}
3
  • Thanks for your comments. If I am understanding right, even 'a' is a constant reference, but through operator "()" which returns a non-constant pointer in the code, we can modify its value, right?
    – Xeh Deng
    Commented Jul 10 at 19:44
  • I post a new test code based on your advice and now I think I understand it. Thanks!
    – Xeh Deng
    Commented Jul 10 at 20:08
  • @XehDeng You're welcome. Commented Jul 11 at 3:51
0
class DateTest{
    public:
        int* dateArray;
        DateTest(){
            dateArray = (int*) malloc(sizeof(int)*3);
            dateArray[0] = 1000;
            dateArray[1] = 12;
            dateArray[2] = 13;
        }
        int& getYear() const{
            return dateArray[0];
        }
};
    DateTest const& date = DateTest();
    int& tmp = date.getYear();
    tmp = 5;
    cout << date.getYear() << endl;

I wrote a simple test to show the reason behind it.
It is due to the fact that a constant reference calls a constant function, but the function does return a non-constant reference.
That's why we could modify the variables.

Not the answer you're looking for? Browse other questions tagged or ask your own question.