I came across some kind of code that seems to be correct. It must provide an open, immutable pointer, while maintaining a mutable, non-private private pointer.
Oddly enough, this code crashed on the SN C ++ Compiler (for the PlayStation 3), but it worked fine on GCC. In SN C ++, data will point to dummy values, and m_data will work as intended.
Code in question:
#include <cstdint> class Foo { public: Foo() : data((const std::uint8_t* const&)m_data) { m_data = nullptr; // Set later in some other member function. } const std::uint8_t* const &data; private: std::uint8_t* m_data; };
Does this code cause undefined behavior? As far as I know, casting to such a link will result in converting (const std::uint8_t* const&)m_data to *reinterpret_cast<const std::uint8_t* const*>(&m_data) .
Test cases:
Foo* new_foo() { return new Foo; }
and looking at the generated disassembly. Note that this is a 64-bit version of PowerPC with 32-bit long and index pointers.
SN C ++: ps3ppusnc -o test-sn.o -O3 -c test.cpp
0000000000000000 <._Z7new_foov>: 0: f8 21 ff 81 stdu r1,-128(r1) # ffffff80 4: 7c 08 02 a6 mflr r0 8: f8 01 00 90 std r0,144(r1) # 90 c: fb e1 00 78 std r31,120(r1) # 78 10: 38 60 00 08 li r3,8 14: 3b e0 00 00 li r31,0 18: 48 00 00 01 bl 18 <._Z7new_foov+0x18> 1c: 60 00 00 00 nop 20: 2c 03 00 00 cmpwi r3,0 24: 41 82 00 38 beq 5c <._Z7new_foov+0x5c> 28: 30 81 00 70 addic r4,r1,112 # 70 2c: 93 e3 00 04 stw r31,4(r3) <-- Set m_data to r31 (0). 30: 60 7f 00 00 ori r31,r3,0 34: 90 83 00 00 stw r4,0(r3) <-- Set data to r4 (r1 + 112 (On stack)?!) 38: 63 e3 00 00 ori r3,r31,0 3c: e8 01 00 90 ld r0,144(r1) # 90 40: 7c 08 03 a6 mtlr r0 44: eb e1 00 78 ld r31,120(r1) # 78 48: 38 21 00 80 addi r1,r1,128 # 80 4c: 4e 80 00 20 blr
GCC 4.1.1: ppu-lv2-g++ -o test-gcc.o -O3 -c test.cpp
0000000000000000 <._Z7new_foov>: 0: 38 60 00 08 li r3,8 4: 7c 08 02 a6 mflr r0 8: f8 21 ff 91 stdu r1,-112(r1) # ffffff90 c: f8 01 00 80 std r0,128(r1) # 80 10: 48 00 00 01 bl 10 <._Z7new_foov+0x10> 14: 60 00 00 00 nop 18: 7c 69 1b 78 mr r9,r3 1c: 38 00 00 00 li r0,0 20: 39 63 00 04 addi r11,r3,4 <-- Compute address of m_data 24: 78 63 00 20 clrldi r3,r3,32 # 20 28: 90 09 00 04 stw r0,4(r9) <-- Set m_data to r0 (0). 2c: e8 01 00 80 ld r0,128(r1) # 80 30: 38 21 00 70 addi r1,r1,112 # 70 34: 91 69 00 00 stw r11,0(r9) <-- Set data reference to m_data. 38: 7c 08 03 a6 mtlr r0 3c: 4e 80 00 20 blr