質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2675閲覧

C++でスマートポインタを使用してメモリを確保したい

nicoyou

総合スコア129

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/03/09 22:46

編集2020/03/10 00:08

C++でスマートポインタを利用してnバイト分のメモリを確保し、失敗した場合はエラー処理を書きました

それを読み込んだファイルデータの保存などの方法で、生のポインタとして使用する場合、
もっと優良(一般的)な書き方はありますか?(Byte型を使うなど)

色々書いた結果一応動くコードが完成しただけなので少し不安です

C++

1int n=100; 2 3std::unique_ptr<void*> buffer(new(std::nothrow) void* [n]); 4if (buffer == nullptr){//メモリを確保できなかった場合の処理 5}

追記:
すみません、上のソースコードはポインタの配列を確保するコードだったようなのですが、
memcpy等のコピー先に使えるような連続したメモリが必要で、配列としては使用しません

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

僕ならこうする:

C++

1#include <iostream> // cout, endl 2#include <memory> // uniqur_ptr, make_unique 3#include <cstdint> // uint8_t 4 5int main() { 6 int n = 10; 7 const char data[] = "abcdefghij"; 8 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(n); 9 10 for ( int i = 0; i <= n; ++i ) { 11 buffer[i] = data[i]; 12 } 13 // できたかな? 14 for ( int i = 0; i < n; ++i ) { 15 std::cout << buffer[i] << ' '; 16 } 17 std::cout << '[' << buffer.get() << ']' << std::endl; 18}

投稿2020/03/09 23:44

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nicoyou

2020/03/09 23:52

ご回答ありがとうございます サンプルプログラムでメモリを配列として確保されていますが、配列として使用しない場合も配列として確保したほうが良いのでしょうか? それともmake_uniqueを使用するために仕方なくで配列として確保されているのでしょうか?
episteme

2020/03/09 23:56

え? 連続した領域なら配列と同義ちゃうん? 先頭ポインタが欲しいならサンプルのとおり get() で得られるし。
nicoyou

2020/03/10 00:07 編集

軽く調べてみたところ、std::unique_ptr<uint8_t[]>としてメモリを確保した場合 []のオーバーロードが使用できるようになると書いていたので、わざわざ使わない[]を付ける必要性はないのではないかと思いました (質問文のコードは間違っていたようなので追記しました) std::unique_ptr<uint8_t> buffer = std::make_unique<uint8_t>(n); (動作するのかは分かっていません) >え? 連続した領域なら配列と同義ちゃうん? そうだと思いますm(__)m
episteme

2020/03/10 00:08

型Tがintを引数とするコンストラクタを持っていた場合、make_unique<T>(n) のnがコンストラクタ引数なのか配列の個数なのか曖昧になるやん。
nicoyou

2020/03/10 00:11

理解しました
guest

0

ベストアンサー

指摘事項が2点あります。

std::unique_ptr<void*> buffer(new(std::nothrow) void* [n]);

n個のvoid*なので、これはポインタの配列を取得します。

if (buffer == nullptr){//メモリを確保できなかった場合の処理

std::unique_ptr::operator boolがあります

c++

1std::unique_ptr<std::byte> buffer(new(std::nothrow) std::byte[n]); 2if(!buffer){ 3 std::cerr << "bad alloc" << std::endl; 4}

例外を使用したくない場合を除き、一般的にはstd::vector<std::byte>で十分です。

追記

std::vectorは連続した領域を確保する事が仕様で定められていますので
(なお、std::vector<bool>は除く)

c++

1 std::unique_ptr<std::byte> buffer(new(std::nothrow) std::byte[n]); 2 memcpy(buffer.get(),"hello",6); 3 std::cout << (char*)buffer.get(); 4 5 std::vector<std::byte> v(n); 6 memcpy(v.data(), "world", 6); 7 std::cout << (char*)v.data() << std::endl; 8 9 std::cout << (char*)&*buffer << (char*)&v[0];

memcpy可能です。

投稿2020/03/09 23:50

編集2020/03/10 00:25
asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nicoyou

2020/03/10 00:07

ご回答ありがとうございます 質問文のコードは正しくなかったようで追記しました おそらくstd::vector<std::byte>は使えないと思います
episteme

2020/03/10 00:23

>おそらくstd::vector<std::byte>は使えないと思います なんで? std::vector<std::byte> buffer(n); std::byte* ptr = &buffer[0]; これ↑ではダメなん?
nicoyou

2020/03/10 00:25

>std::vectorは連続した領域を確保する事が仕様で定められていますので 一方向listの様なものだと思っていました 覚えておきますm(__)m
episteme

2020/03/10 00:30 編集

vector, array, string は連続領域が確保されることが言語(ライブラリ)仕様で規定されています。ご安心を。 # 単方向リストは std::forward_list が用意されています
nicoyou

2020/03/10 00:31

お二方のご回答ありがとうございました どちらも参考になったのですが、メモリ確保できなかった処理を含めて、私のコードの間違いを指摘して修正していただいたのでasmさんをベストアンサーに選ばさせていただきました
asm

2020/03/10 00:31

ただし、キャパシティ以上に拡張した際に移動しますので コンストラクタやreserveでの指定をサボったりすると駄目な事もあります
nicoyou

2020/03/10 00:32

>vector, array, string は連続領域が確保されることが言語(ライブラリ)仕様で規定されています。ご安心を。 ># 単方向リストは std::forward_list が用意されています stringやarrayは感覚的に理解していたのですが、vectorは知りませんでした std::forward_listの存在も覚えておこうと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問