2016-07-04 4 views
0

Ich möchte unique und shared_ptr verwenden, um den zugewiesenen Speicher zu verwalten. Aber soweit ich sehen kann, ist der Zugriff auf den Speicher (get, ...) immer const und gibt const Zeiger zurück, so dass ich den gespeicherten Speicher nicht manipulieren kann.Wie kann ich den von std :: shared_ptr (unique_ptr) geschützten Speicher ändern?

Beispiel:

std::unique_ptr<int[]> ptr(new int[42]); 

memset(ptr.get(),0,42*sizeof(int)); //not possible ptr.get() returns const pointer 

Gibt es um eine Arbeit? Wenn es keine Möglichkeit gibt, den Speicher zu manipulieren, welche Gründe gibt es, eine solche Schnittstelle nicht anzubieten?

+1

Warum wollen Sie 'memset' benutzen? Und warum benutzt man statt eines 'std :: vector' ein' std :: unique_ptr '? – TartanLlama

+0

Sie können nicht stehlen Speicher (Besitz Besitz wie Release) von std :: vector – user1235183

+1

@ user1235183 es ​​ist ein 'const Zeiger', nicht ein' Zeiger auf const' Sie können den Inhalt ändern, auf den es ohne Probleme zeigt. Aber Sie benötigen möglicherweise einige Umwandlungen, wenn Sie c-Funktionen wie memset verwenden möchten. – PeterT

Antwort

3

Die Funktion Signatur für std::unique_ptr::get ist

pointer get() const;

die Art der pointer wobei „std::remove_reference<Deleter>::type::pointer wenn diese Art vorhanden ist, sonst T*

Die einzige const daß Signatur für die Funktion ist, selbst, so dass es auf eine const std::unique_ptr<int> a;

So Ihre Prämisse von 012 aufgerufen werden kannist nicht wahr. Sie können den Speicher, auf den ein intelligenter Zeiger zeigt, über einen Zeiger ändern, der von seiner Elementfunktion get() abgerufen wird.

Zusätzlich memset(ptr.get(),0,42*sizeof(int)); ist auch in Ordnung und braucht keine Abgüsse, weil Sie noch implizit alle Zeiger auf einen void-Zeiger nach this pointer-conversion rule umwandeln kann:

A prvalue pointer to any (optionally cv-qualified) object type T can be converted to a prvalue pointer to (identically cv-qualified) void. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.

So hat Ihr Code keine Probleme und scheint dem Standard entsprechen.

2

Nun, dass die Mechanik von std::unique_ptr<>::get() verstanden wird, können Sie einen Wert in einem mehr idiomatischen Algorithmus-basierten Ansatz sehen.

Es ist besser lesbar, vermeidet Umwandlungen, wird funktionieren, sollten Sie Ihre Meinung über den zugrunde liegenden Speicher ändern und ist genauso effizient.

einige Beispiele:

std::fill(ptr.get(), ptr.get() + 42, 0); 

std::fill(&ptr[0], &ptr[42], 0); 

std::fill(std::addressof(ptr[0]), std::addressof(ptr[42]), 0); 

und mit einem kleinen Textvorschlag:

for (auto& x : linear_range(ptr.get(), 42)) { 
    x = 0; 
} 

Mit Optimierungen aktiviert ist, alle diese auswerten zu der gleichen effizienten Code.

vorformulierten ist hier:

template<class I1, class I2> 
struct range_impl { 

    auto begin() const { return i1; } 
    auto end() const { return i2; } 
    I1 i1; 
    I2 i2; 
}; 

template<class I1, class I2> 
auto range(I1 i1, I2 i2) { 
    return range_impl<I1, I2> { i1, i2 }; 
} 

template<class I1> 
auto linear_range(I1 i1, std::size_t length) { 
    return range(i1, std::next(i1, length)); 
} 
Verwandte Themen