Is it impossible to return a link to a constant pointer to const data?

I am having some problems trying to return a link to a const pointer to const . In the following code, get_pC returns a reference to a constant pointer to data:

#include <iostream> using namespace std; class C { public: double c; }; class A { public: C* pC; A(const double val):pC(new C){pC->c=val;}; }; class B { public: const A* pA; B(const A& a):pA(&a){}; C * const & get_pC() const { return pA->pC; } }; int main() { A a(3.7); B b(a); C * const & r = b.get_pC(); r->c=2.2; cout<<(long) &b.pA->pC<<endl; cout<<(long) &r<<endl; } 

Having compiled this code, there is no error, therefore it is allowed to change "c" through "r". This is normal. Moreover, the address b.pA-> pC corresponds to the address r. It's nice too ^ _ ^

But, when I try to prohibit the modification of "c" through "r", I experience problems. If I add const to the r declaration:

 const C * const & r = b.get_pC(); 

then the compiler complains about the modification of "c". Well, thatโ€™s exactly what I want ... right? Unfortunately no, now the addresses "r" and b.pA-> pC are different!

Is it impossible to do what I'm trying to do? I know that one could do something โ€œsimilarโ€ by returning a pointer instead of a link:

 const C * const * get_pC() const { return &pA->pC; } const C * const * r = b.get_pC(); 

but this will add one level of indirection, and I'm curious to know if this is really impossible, or is there a way to make it work with links.

+5
source share
2 answers

The simplest version of the "problem" would be:

 int x; int *p = &x; int* const& r1 = p; const int* const& r2 = p; 

In this case, r1 bound directly to p , therefore &r1 == &p . However, r2 cannot directly bind to p . Instead, line r2 creates a temporary object const int * and binds r2 to a temporary one.

This is always an option when using const lvalue references; if the type is not suitable for direct binding, but there is an implicit conversion, then a temporary one can be created.

To avoid temporary use, you need to use a listing:

 const int* const & r2 = const_cast<const int* &>(p); 

or in the source code:

 const C * const & r = const_cast<const C * &>(b.get_pC()); 

Note. He believed that bad style stores the address of what was passed by reference (since the caller does not expect this to happen, and the object may end in its life cycle). Think about redesigning your code, rather than using this const_cast solution; e.g. use C * const * get_pC() const { return &pA->pC; } C * const * get_pC() const { return &pA->pC; } and const C * const * r = b.get_pC();


To summarize the corresponding link binding rule: links are linked directly only if two types are the same (or a base class link can be associated with a derived class), and the type of the left side may have additional top-level qualifiers, for more details see here or [dcl .init.ref] in the Standard section.

+6
source

Unfortunately no, now the addresses r and b.pA->pC are different from each other.

I assume that in the process of converting C * const & to C const* const & compiler creates a temporary type C const* and r is a reference to it. As if you are using:

 C const* temp = b.get_pC(); C const* const& r = temp; 
+3
source

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


All Articles