トップページ⇒prog
26コメント10KB

std::vectorの質問

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@1周年NGNG
std::vector<int> v(1);
std::vector<int>* pv = &v;
pv[0] = 1; // エラー
(*pv)[0] = 2; // OK

VC++の場合、3行目でコンパイルエラーになります。
コンパイラによってはOKのようです。
仕方なく4行目のように書いていますが、どうも嫌です。
みなさんはどうしていますか?

ところでSTLの話題ってあまりないけど、なぜでしょう?
使いこなしているか、使わないかのどちらかなの?
0002名無しさん@1周年NGNG
違うかもしれないけど、もしかしてnamespaceの問題?
00032NGNG
よく読んだら、やっぱり全然違ったね。上のは無視して下さい。

で、pv[0]の型はint型ではなくstd::vector<int>型だから1は代入できなくて当たり前。
0004名無しさん@1周年NGNG
ポインタじゃなくてイテレータとか使うとか
関数の引数の場合は参照にするとかじゃないかなあ
0005名無しさん@1周年NGNG
>>1

int i = 128;
int *pi = &i;
pi[0] = 50;

i はいくつになりましたか?
pi[0] は何を意味していると思いますか?
00061NGNG
4行目のようにやれって事?
普通の配列のように使いたいけれど残念だな。

>5
i は配列じゃないし。
std::vectorは可変長なのです。
0007>1NGNG
typedef で乗り切れ

> で、pv[0]の型はint型ではなくstd::vector<int>型だから1は代入できなくて当たり前。

が全部説明してるからこのスレは

*********** 終了 ***********
0008名無しさん@1周年NGNG
えー pvをint*で宣言すればいいんじゃね〜の?
int* pv = v.begin();
vectorは、こー言う使い方保証されてないっけ?
0009名無しさん@1周年NGNG
v.begin()が返すのはstd::vector<int>::iteratorですよ。
実はint*かもしれないけど。
0010これって許される?NGNG
int* pv = &*v.begin();
0011名無しさん@1周年NGNG
>>10
&(*v.begin()).at(/*ここに適当な整数*/);じゃないかなあ
vectorそのものは配列じゃなくて一つの変数のような
0012名無しさん@1周年NGNG
>10
本当はだめ。
でも事実上ほぼ問題なし。
でも最新のgccのライブラリじゃだめみたい。

ちなみに、「プログラミング言語C++ 第3版」では、
『慣習的な定義のvectorなら、それぞれT*、const T*を使うこと
だろう』
となっている(iterator@`const_iteratorの型について)
つまり普通そうだけど決め付けんなよ、という意味でしょう。

というわけで、そのコードをどの程度ポータブルにしたいかに
よる。
0013名無しさん@1周年NGNG
その場は許されるけど
vector<T>::iterator::operator*()ってTを返すのだから
その&はint*というのは正しいかもしれない。

pv++というような操作をしてもいいとは思えないですが。

STLの"定義"そのものに明るくないのですが
とりあえず、MS-CについているSTLでは
template<class T>
class allocator {
typedef T* pointer;
.
.
};
template<class T@` class A = allocator<T> >
class vector {
typedef A::pointer iterator;
.
.
};
vector::iteratorの定義としては、これは実装によらず
真なんでしょうか?
ならvector<T>::iterator = T*とみなして扱っても問題ないと思います。
でもなんで素直に、std::vector<int>::iterator pv = v.begin();
にしないの?
001411NGNG
11は間違え。勘違いしてた(恥)
001510NGNG
用途としてはCの関数にvectorを渡す場合です。
T*を使わないvectorの実装は無いだろうと思ってましたが
どうやらありそうですね。
0016名無しさん@1周年NGNG
vectorそのものよりallocatorの問題と思います。
vector<int@` file_allocator<int> > で
file_allocatorがメモリ上に割り当てるのではなく
ファイル上に割り当てるallocatorなんて場合とか
0017名無しさん@1周年NGNG
>16
違う。

template <class T>
class vector {
typedef T* iterator;
typedef const T* const_iterator;
};

が保証されていないということ。すなわち、

template <class T>
class vector {
class iterator {};
class const_iterator{};
};

かもしれないということ。ついでに10について答えれば、

class reference {
};

class iterator {
reference operator*(){retrun reference(foo@`bar);}
};

なんて定義されている可能性もある。
だから厳密にはだめ。
でも普通そうはなってないのでポータブルでなくていいなら
iterator==T*と思ってしまっても実害はない。
001810NGNG
*v.begin() で一度デリファレンスしているので、iterator が T* で
なくてもいいと思います。それよりもTの集合が順番通り連続したメモリに
確保されているかどうかが問題になるのではないでしょうか。
0019名無しさん@1周年NGNG
>10
iteratorのoperator*がclass referenceを返すものだった場合、
&(*begin())はreferenceのアドレスを返してしまう。
class referenceでopreator&をオーバーロードしてるとはあまり
期待できないから(vector<bool>みたいにどうにもならないのもある)
結局だめだと思う。
0020名無しさん@1周年NGNG
19の続き
どのみち、メモリ的に連続してるかどうかにかかってくるんだったら、
それを前提にしたらどうやってもポータブルにはならないんだから、
コピーがイヤなら素直にポータビリティをあきらめて
iterator==T*と決め付けてコード書けばいいんじゃない。
002110>19@`20NGNG
なんかよくわからなくなってきました。
*がclass referenceを返す実装だったらvector<int>の*begin()の
型はintでなくなるということですね。でもその場合どうやってintを
取り出すのでしょうか。17の後半のコードが完成形を見てみたいです。
20はまったくその通りです。
0022名無しさん@1周年NGNG
右辺値にするときはvector<T>::reference::operator T()constでキャスト。
左辺値にするときはvector<T>::reference::operator=(const T& x)が呼ばれる。
(もちろん普通はこうなってない。)
vector<bool>の実装を見れば参考になると思う。
gccのvectorもこんな感じじゃないかな? 見てないから知らないけど。
002310NGNG
なるほど、わかってきました。そうすると printf("%d\n"@` *v.begin())
なんてのはキャストしないとダメって事ですね。でもboolは特殊なのでいいとして
汎用型でこういう事をやられるとすごく使いづらいような気がします。
要素へのポインタが取れないという事はずっとiteratorとしてハンドリング
しなければならないという事になり、それはちょっとという気分です。
私が未熟モノでした。
002419@`20NGNG
>なんてのはキャストしないとダメって事ですね。でもboolは特殊なのでいいとして
>汎用型でこういう事をやられるとすごく使いづらいような気がします。

俺もそう思った。なんかわかんなくなってきた(笑)。
もしかしたら&(*begin())はT*でいいのかも。
よかったら引き続き調べてくだされ。
002519@`20NGNG
気になるので調べてみた。

「プログラミング言語C++ 第3版」p.518に、
『リファレンスは、要素アクセスに適した型である。
単純でわかりやすいvector<X>の実装では、referenceは
X&、const_referenceはconst X&である。』
とかかれている。

つまり、
・要素アクセスに適した型である、以上のことは決まってない。
・reference==X&とは限らない
ようなので、やっぱり&(*begin())==T*と言い切れる、
とは考えにくい。
002610NGNG
うーん、たしかにそう書いてありますね。
refernce が X& でなかった場合、次のコードは移植性が無いと
いうことなんですね。
struct s {int i;}; vector<s> v(1); v.front().i = 1;
こんなのよく使ってるなあ。もうvector使うのやめようかなあ。
■ このスレッドは過去ログ倉庫に格納されています