Sappiamo tutti che le cose di questo tipo sono validi in C++:const riferimento alla stranezza temporanea
const T &x = T();
mentre:
T &x = T();
non è.
In a recent question la conversazione porta a questa regola. L'OP aveva pubblicato un codice che evoca chiaramente UB. Ma avrei aspettare una versione modificata di farlo funzionare (Questa è la versione modificata):
#include <iostream>
using namespace std;
class A {
public:
A(int k) { _k = k; };
int get() const { return _k; };
int _k;
};
class B {
public:
B(const A& a) : _a(a) {}
void b() { cout << _a.get(); }
const A& _a;
};
B* f() {
return new B(A(10));
}
int main() {
f()->b();
}
Questa stampa materiale privo di su alcune macchine, 10 sugli altri ... suona come UB per me :-). Ma poi ho pensato, bene A
è fondamentalmente un glorificato int
tutto ciò che inizializza uno e leggerlo. Perché non basta chiamare un A
int
e vedere cosa succede:
#include <iostream>
using namespace std;
typedef int A;
class B {
public:
B(const A& a) : _a(a) {}
void b() { cout << _a; }
const A& _a;
};
B* f() {
return new B(A(10));
}
int main() {
f()->b();
}
esso stampa 10
ogni volta. Almeno sembra come la regola di riferimento const è valida per la versione int
, ma non per la versione di classe. Sono entrambi semplicemente UB a causa dell'uso dell'heap? Sono solo fortunato con la versione int
perché la compilazione ha visto tutti gli const
s e ha appena stampato direttamente uno 10
? Quale aspetto della regola mi manca?
Ti suggerisco di cambiare "un riferimento const" a "un riferimento const * locale * per rendere le cose ancora più chiare;) – fredoverflow
@FredOverflow: Perché stai insistendo su un riferimento * local *? Puoi dichiarare legalmente 'const std :: string & r =" Hello "' in ambito namespace e ottenere la stessa estensione lifetime. – AnT
@AndreyT, come viene stabilito questo * collegamento * a quale livello? –