Vorrei eseguire un'iterazione su un array float pre-allocato con un contenitore personalizzato che non possiede i dati, ma che agisce su un segmento di esso. Esempio, nominando la classe contenitore LinhaSobre
:Regole per la restituzione di riferimenti a oggetti falsi in C++
std::unique_ptr<float[]> data(new float[720]);
...
//creates container to iterate 26 floats starting from from data[12]
LinhaSobre cont(data.get()+12, 26);
//sets those elements to 1.5
for(size_t i = 0; i < cont.size(); i++)
cont[i] = 1.5f;
Ecco una possibile implementazione del operator[]
:
//...
//LinhaSobre has a member mem0 which is initialized
//as a pointer to where the interval starts
float & LinhaSobre::operator[] (size_t i)
{
return *(mem0+i);
}
Si noti che sto tornando un riferimento da LinhaSobre::operator[]
a dati che non si possiede. Non dovrebbe interferire con la durata dei dati (costruttori, distruttori).
Ora desidero esporre lo data
memorizzato con un altro motivo, std::array<float,4>
e non puro float
. Esempio, nominando la nuova classe LinhaSobre4f
:
std::unique_ptr<float[]> data(new float[720]);
...
//creates container to iterate 4 array<float, 4> starting from from data[12]
LinhaSobre4f l(data.get()+(3*4), 4);
//sets those elements to {1.5f, 2.5f, 3.5f, 4.5f};
for(size_t i = 0; i < l.size(); i++)
l[i] = { {1.5f, 2.5f, 3.5f, 4.5f} };
Si noti che io tratto le voci come una matrice. Ciò porterebbe ad alcuni cambiamenti nella classe contenitore, la mia preoccupazione principale è con il operator[]
, ecco il codice completo della classe:
struct LinhaSobre4f
{
LinhaSobre4f(float * pos_begin, size_t size_):
pos0(pos_begin),
size_(size_){}
std::array<float, 4> & operator[](size_t i)const
{
std::array<float,4> * r =
reinterpret_cast<std::array<float,4>*> (pos0+(4*i));
return *r;
}
size_t size()const
{
return size_;
}
private:
float * pos0;
size_t size_;
};
Il operator[]
restituisce un riferimento a un blocco di memoria trattato come un std::array<float,4>
che mai esisteva come tale, ma data la garanzia del layout di memoria std::array
, funziona. Sono dubbioso su questo, va bene? (a parte l'allineamento della memoria, che garantirò). Sono autorizzato a esporre un oggetto come questo, semanticamente? Qual è il termine corretto per questo? (Ho usato oggetto falso nel titolo).
Here's a live demo of the example. Here's another (the other link sometimes fails)
Una cosa che sicuramente mi distingue (e il compilatore ti avviserà di questo) è che in 'operator []' di 'LinhaSobre4f' stai restituendo un riferimento a una variabile temporanea - dovresti cambiare la firma di questo metodo per restituire per valore invece di riferimento. – ArchbishopOfBanterbury
(Am I?) La variabile locale (temporanea) è un puntatore, e sto restituendo il dereferenziamento di esso, non un riferimento ad esso. – Kahler
I * penso * che tu sia al sicuro, anche se non ho nulla a cui fare il backup. – vu1p3n0x