Sto utilizzando boost :: make_shared per la prima volta per creare oggetti puntati da puntatori condivisi. Soprattutto perché il nostro codice era troppo lento e la singola allocazione ha davvero contribuito a migliorare le prestazioni.boost :: make_shared non sta chiamando l'operatore (posizionamento) nuovo?
Dopo aver risolto alcune perdite di memoria "il modo manuale difficile" ho deciso di implementare un rilevatore di perdite di memoria semplice sostituendo i nuovi operatori per tutte le classi rilevanti solo per contare quali oggetti sono ancora vivi in punti specifici della nostra applicazione. L'ho già implementato più volte e sono rimasto sorpreso nel constatare che il mio codice non rileva più alcun oggetto.
Ho pensato che tutto quello che dovevo fare è override "nuova collocazione" al posto dell'operatore "normale" nuove di a causa dei seguenti dalla documentazione sito spinta per make_shared:
"Effetti: Alloca memoria adatto per un oggetto di tipo T e costruisce un oggetto tramite il posizionamento nuova espressione nuova (pv) T() o nuova (pv) T (std :: forward (args) ...). allocate_shared utilizza una copia di a per allocare memoria.Se viene generata un'eccezione, non ha l'effetto ".
Anche il mio inserimento nuovo non viene chiamato. Ho scritto un piccolo programma di test per riprodurre il comportamento:
#include <iostream>
using namespace std;
#include "boost/shared_ptr.hpp"
#include "boost/make_shared.hpp"
class Test
{
public:
Test() { cout << "Test::Test()" << endl; }
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Test new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
cout << "Test non-throwing new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, void* ptr) throw() {
cout << "Test non-throwing placement new" << endl;
return malloc(size);
}
};
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Global new" << endl;
return malloc(size);
}
int main() {
cout << "..." << endl;
boost::shared_ptr<Test> t1(boost::make_shared<Test>());
cout << "..." << endl;
boost::shared_ptr<Test> t2(new Test());
cout << "..." << endl;
return 0;
}
che rende il seguente output:
...
Global new
Test::Test()
...
Test new
Test::Test()
Global new
...
mi aspettavo "Test non gettare nuova collocazione" al 3 ° riga di output. Cosa pensi che dovrebbe essere il comportamento? Sei d'accordo che secondo la documentazione di make_shared dovrebbe chiamare il nuovo operatore della mia classe di test? O l'ho frainteso?
Potrei copiare localmente l'implementazione di boost e aggiungere una chiamata al nuovo operatore di posizionamento, ovviamente. Ma sarebbe appropriato o violerebbe la semantica del collocamento nuovo?
Grazie in anticipo per il vostro tempo e il vostro aiuto.
Osservando boost, sta utilizzando il nuovo posizionamento globale operator :: new (pv) T(). Ecco perché il posizionamento a livello di classe non viene chiamato ... Rimuovendo il qualificatore globale '::' prima del nuovo, make_shared chiama effettivamente il nuovo operatore di posizionamento a livello di classe. –
Gob00st