vector の最後の要素+1 へのポインタは取っていい?

解決


tetrapod  2012-04-06 13:42:45  No: 73307  IP: 192.*.*.*

単純配列 int a[4]; に対して a+4 が valid であることは保証されていますが
std::vector<T> v(4); に対して v+4 (に相当するポインタ) は valid なんでしたっけ?
(もちろん [ポインタ値] をとるだけで dereference しない前提)

ISO/IEC 14882:1998 を探した範囲では 23.1.1 で
「at() は n>=v.size() で例外を投げる」
としか書いてないのでなんとも判断がつきかねます。
C++11 で追補とかでてましたっけ?

もともと char a[] の要素を char* でぐりぐりまわすコードがあって
可変長になったので char[] を vector に変えたら
&v[v.size()] で VC++ 2005/2010 は例外投げてくれるので困っております。
_SECURE_SCL や _HAS_ITERATOR_DEBUGGING で回避できるのはわかってますが
そもそも前提として &v[v.size()] を計算してよいのかどうか保証が欲しい。

編集 削除
仲澤@失業者  2012-04-06 16:29:28  No: 73308  IP: 192.*.*.*

消極的にはsize が 0のときは、常にアウトだと考えるべき
なので、一般的サイズでもだめなんじゃないでしょうか。
(まったく自信無し。きっぱり)

編集 削除
επιστημη  URL  2012-04-07 06:43:16  No: 73309  IP: 192.*.*.*

vector(string,array)はその内部表現がリニアであることを保証しているはず。
なので !v.empty() ならば
&v[0]+v.size() でいぃんじゃないかいら。

編集 削除
tetrapod  2012-04-08 17:46:40  No: 73310  IP: 192.*.*.*

a+N をとってよいのは T a[N]; に限らず new T [n] のときも同等、
vector は new T [n] 相当 (要素の連続性保証より) 、
だから &v[0]+v.size() は妥当 (empty でないとき) っすか?

根拠としてちょっと弱い気が・・・言語仕様書の文言として何かないか、
(特に C++11 で)というのを期待しているのです。
# まあ VS2005/2010 なので C++11 に文言があっても無意味なんですが

実装上問題ないのは確認済み、っつことで rationale 期待中。

編集 削除
επιστημη  URL  2012-04-08 21:19:45  No: 73311  IP: 192.*.*.*

> 実装上問題ないのは確認済み、っつことで rationale 期待中。

これ↓でいっすか?

N3376 23.3.6.1 Class template vector overview
... The elements of a vector are stored contiguously, 
meaning that if v is a vector<T, Allocator> where T is 
some type other than bool, then it obeys the identity 
&v[n] == &v[0] + n for all 0 <= n < v.size().

編集 削除
tetrapod  2012-04-09 08:58:59  No: 73312  IP: 192.*.*.*

a+N が1つ先を指せるという規定は 5.7 Additive operators にあり、
8.3.4 Arrays にも 8.3.1 Pointers にも記述がないわけで
その意味で 23 containers や 23.2.4 template class vector に記述がないのは
ある意味当たり前なような気がしてきたっす。

> N3376
これは正式採択版規格書では 23.2.4 (vector) の 1 に対する補足として
1998 版に無かった記述が
2003 版に追加されている
代物なわけですが、虚心坦懐にこの文言を読む限りにおいてだと
n==v.size() のときは保証外ということになるのでは?
使っちゃダメという根拠にはなってもつかっていい根拠にならないです。

3回転半ひねりを加えて邪悪にこの文言を読むと
・ vector の要素の列が a[N] と同等としてよい
・ &v[0] は iterator ではなくて単にポインタ右辺値である
・ポインタと整数の加減算において1つ先は指すことが認められている
となり &v[0]+v.size() は問題ないことになりますが・・・

&v[0]+v.size() が問題なくても
&v[v.size()] の保証は依然無いことになりますけど。

編集 削除
επιστημη  URL  2012-04-11 05:46:55  No: 73313  IP: 192.*.*.*

「vector内の要素はリニアに確保される」と
「&v[0] は領域の先頭である」から
自然に(自明に)導出されるんじゃないすかねぇ...

編集 削除
fdas  2012-04-11 12:28:05  No: 73314  IP: 192.*.*.*

この手のことは試せば失敗するのですぐに確認できる。

しかしなんでこう面倒なことをわざわざ考えるかなw

編集 削除
επιστημη  URL  2012-04-11 19:16:14  No: 73315  IP: 192.*.*.*

↑いやいや、言語/ライブラリの仕様としてはどうなのよってハナシ
してるとこで「試せば失敗するのですぐに確認できる」は意味を持たない。

編集 削除
fdsa  2012-04-12 02:31:54  No: 73316  IP: 192.*.*.*

あぁなるぼどね。
まぁ言語仕様を深堀してどの程度ウマいのかは謎だけど。

編集 削除
επιστημη  URL  2012-04-12 05:18:37  No: 73317  IP: 192.*.*.*

標準準拠な処理系でならどれでも通るコードを
狙ってるなら仕様に照らすしかないっしょ。

編集 削除
tetrapod  2012-04-18 08:32:44  No: 73318  IP: 192.*.*.*

# 変な sp*m 業者?が age ているが...

a+N が valid なのは 5.7 の規定であること
23.2.4 の解説は n==v.size() を認めていないこと
より、言語規格書レベルで話をするなら(実在処理系での実装はおいといて)

&v[0]+v.size() は valid
&v[v.size()] は invalid
っつことでファイナルアンサーにしておきますです。

編集 削除