2016-07-04 6 views
0

割り当てられたメモリの世話をするためにuniqueとshared_ptrを使いたいと思います。しかし、私が見る限り、メモリへのアクセス(get、...)は常にconstであり、constポインタを返すので、格納されたメモリを操作することはできません。std :: shared_ptr(unique_ptr)でガードされたメモリを変更する方法

例:

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

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

は仕事の周りにはありますか?メモリを操作する方法がない場合、そのようなインターフェイスを提供しないという設計上の理由は何ですか?

+1

は、なぜあなたは 'memset'を使用するようにしたいですか?なぜ 'std :: unique_ptr 'を 'std :: vector'の代わりに使うのですか? – TartanLlama

+0

std :: vector – user1235183

+1

@ user1235183からメモリを盗むことはできません(リリースのような所有権を得てください)。これは 'const pointer'で、' constへのポインタ 'ではなく、問題のない内容を変更することができます。しかし、memsetのようなc関数を使いたいなら、いくつかのキャストが必要かもしれません。 – PeterT

答えて

3

、「その型が存在する場合、std::remove_reference<Deleter>::type::pointerさもなければT*std::unique_ptr::getの関数シグネチャはpointerのタイプがある

pointer get() const;

ある

その署名にのみconstは、関数自体のためでありますそのためにはconst std::unique_ptr<int> a;

012のあなたの前提は真ではありません。スマートポインタが指すメモリは、get()メンバ関数から取得したポインタによって変更できます。

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.

だから、あなたのコードは何の問題を持っていないと思わ:

さらにmemset(ptr.get(),0,42*sizeof(int));あなたはまだ、暗黙的this pointer-conversion ruleに従ってボイドポインタに任意のポインタに変換することができますので、も結構ですし、任意のキャストを必要としません。標準に準拠すること。

2

std::unique_ptr<>::get()の仕組みが分かったので、より慣用的なアルゴリズムベースのアプローチでは、いくつかの価値があるかもしれません。

おそらく、読みやすく、キャストを避け、基礎となるストレージについてのあなたの心を変えなければなりませんし、効率的です。

いくつかの例は:

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); 

と少しの定型と

:最適化が有効になって

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

と、これらのすべてが同じ効率的なコードに評価されます。

定型はここにある:

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)); 
} 
関連する問題