5ちゃんねる ★スマホ版★ ■掲示板に戻る■ 全部 1- 最新50  

■ このスレッドは過去ログ倉庫に格納されています

【注意】STLの落とし穴【危険】

1 :デフォルトの名無しさん:04/12/27 05:23:44
STL(あるいはboost)を使っていく上で
思わぬ落とし穴、やってはいけない禁じ手などを
晒すためのスレです。暗黙知の解放!


2 :デフォルトの名無しさん:04/12/27 05:30:53
vector<auto_ptr>


3 :デフォルトの名無しさん:04/12/27 05:57:34
vectorやstringで、.clear()したからといって
メモリも解放されるとは限らない罠。


4 :デフォルトの名無しさん:04/12/27 05:58:20
>>2
ん!?危険なの?ちと想像してみよかな・・・


5 :デフォルトの名無しさん:04/12/27 06:40:36
>>4
std::sort()などのコピーを伴うアルゴリズムを呼び出した時の事を考えてみろ。
普通ポインタのコピーをしても、ポインタが指しているインスタンスは変化しないという
考えの元に各種アルゴリズムが構築されている。

しかし、std::auto_ptrは、ポインタをコピーするだけで、元のポインタの値は 0 に設定
されてしまう。これにより、複数のポインタから同一のインスタンスを指す事のないように
してあるのがstd::auto_ptrだ。だからこそstd::auto_ptrのスコープを外れた時点で、それ
が指すインスタンスもdeleteできる。

すなわち、コピーコンストラクタと代入演算子のセマンティックスが独自の物で、通常の
ポインタとは全く互換性がない。

6 :デフォルトの名無しさん:04/12/27 06:49:33
gcc3以降では、auto_ptrをstlコンテナに入れてるソースは
コンパイルエラーになるようになってるしね。

7 :デフォルトの名無しさん:04/12/27 07:32:31
関連?重複?
C言語の見えないバグ、対処法でも語るスレ
http://pc5.2ch.net/test/read.cgi/tech/1064482029/l50

8 :デフォルトの名無しさん:04/12/27 07:48:05
>>7
C厨と合流するつもりはない。

9 :デフォルトの名無しさん:04/12/27 07:55:32
auto_ptrはほとんど使わないな。
非常に使いにくい。

10 :デフォルトの名無しさん:04/12/27 07:59:47
落とし穴つったらアレだろ
コンパイラが対応してないwwwwww

11 :デフォルトの名無しさん:04/12/27 11:22:44
>>10
STLもまともに機能しない糞コンパイラなぞ捨ててしまえ。

12 :デフォルトの名無しさん:04/12/27 12:24:35
糞スレ立てんなよ、バーカ 死ね>>1

13 :デフォルトの名無しさん:04/12/27 12:46:56
EffectiveSTLに書いてある以外の落とし穴があるなら
是非知りたいけど

14 :デフォルトの名無しさん:04/12/27 22:29:09
>>6
それは、普通でしょう。 auto_ptrはstlのコンテナとは共存できない。

Exceptional C++: Item 37. AUTO_PTR を読みましょう。
ちなみに、auto_ptrをコンテナで使おうとするとエラーが出るのは、Exceptional C++によれば、

auto_ptr's copy constructor and copy assignment operator take references to non-const to
the right-hand-side object. Most implementations of the standard containers' single-element
insert() functions take a reference to const, and hence won't work with auto_ptrs.

とのこと。 boostのshared_ptrは便利だよ。

15 :デフォルトの名無しさん:04/12/28 00:16:50
stringの参照渡しではなく、実体渡しってコスト高いのかな・・・

例えば、1000文字程度の文字列が格納されてるstringを関数の引数などで
実体渡しだとか、返却すると高いのかな?

string tail( string a)
{
return a + ":addtail";
}

みたいなコード。
参照渡しって微妙に使いにくいんだよね・・・だから実体渡しにしたいの
だけど。


16 :デフォルトの名無しさん:04/12/28 00:20:41
>>15
stringの実装方法による。大抵のstringは文字列そのものを別の領域にもっており、
コピーコンストラクタでコピーされるのは管理領域だけという場合が多い。
それよりも、関数内での演算時にコンストラクタが呼び出され、そちらはまともに内容の
方もコピーするので、間違いなく遅くなるぞ。

17 :デフォルトの名無しさん:04/12/28 01:53:25
>>15
それでいいと思う。 最近のコンパイラって結構賢いし、あんまり細かいことは気にしない
方がいい。 stringも大抵はリファレンスカウント方式だから、コピーのコストは低い。
ちなみに、C++ではmake copying cheaperは一つの鉄則。 特に、STLユーザーは。
(Effective STL: Item 3参照) C++でもJavaみたいにプログラミングするのがいいみたい。

また、Efficent C++ Chapter 4. The Return Value Optimization参照するといい。


18 :デフォルトの名無しさん:04/12/28 03:23:48
>>16,17

ほうほう、なるほど。
んじゃ、stringの場合、もう参照渡しにする理由なんてない
気がするなー。
サンクス。


19 :デフォルトの名無しさん:04/12/28 03:44:29
>>18
Efficient C++でも読んでみるといいかも。

20 :デフォルトの名無しさん:04/12/28 05:20:05
便乗して自分も質問・・・
vector< string > なんかを返却するのは危険だろうか?
例えばの用途としては、ファイル名を列挙するサービスを作ったとして、
その場合、なんらかの形で配列を返しますけど、安全性考えるなら
vectorだとか使いたいところ。それも、返却で。

アセンブリリスト出力させても、いまいち分からないし。
特にSTL内部の謎シンボルにcallだとかjumpされるともう追えない (;-;)


21 :デフォルトの名無しさん:04/12/28 05:23:12
>>20
危険でも何でもない。std::vectorのコピーコンストラクタが全部面倒みてくれる。
もちろん参照を返す場合は、ローカル変数の参照を返してはいけない事などは
他のクラスやPODと同じ。

22 :デフォルトの名無しさん:04/12/28 05:27:16
逆落とし穴?ってとこかな。有名だけど、一応足跡残しとこうかな。

vector<>ってアドレス的に連続性が保障されてるって、みなさん
知ってました?

例えば、vector< char > tbl;
とあって、tbl.size()==nな場合、
tbl[0]からtbl[n-1]は連続したアドレスであることが保障されてるんだってさ。STLの仕様として。

なので、char*p = &tbl[0] とかやって、その後は *p++ = 0x00 だとかで
アクセスできてしまうと。iteratorを使う必要もないみたい。

でもdequeでは、保障されてるのか、保障されてないのか不明。
明記された文書も見たこと無い。
listあたりだと確実に連続してないので、気にならないけど
dequeは気になるなー。


23 :デフォルトの名無しさん:04/12/28 05:29:38
>>危険でも何でもない。std::vectorのコピーコンストラクタが全部面倒みてくれる。
あ、いや、おそらく20はそのコピーコンストラクタのコストを気にしてると
思うんですが。例えば、stringが100個くらいあったとして、それを返却すると
関数出口で発動するコピーコンストラクタがまじでコピーしているのか否か?など。


24 :デフォルトの名無しさん:04/12/28 05:31:40
>>22
ISO/IEC14882:2003ではstd::vectorの連続性が保証されてるよ。
§23.2.4の当たり。
std::dequeは保証されてない。

25 :22:04/12/28 05:32:35
ついでに調子こいて。
vector<bool>の時だけは特殊カスタマイズ発動して、ビット操作を意識した
コードが生成されるみたい。ビットセットなんかでメモリかつかつの時は
積極的にvector<bool>を使うといいみたい。


26 :デフォルトの名無しさん:04/12/28 05:34:04
>>23
それだったら、std::vectorの実装による、としかいいようがない。
Copy On Writeなら、要素を変更しようとしない限り、管理情報のみを返すかもしれない。
const参照なら戻り値最適化をしてくれる可能性がさらに高まる。

27 :デフォルトの名無しさん:04/12/28 05:34:10
vector<bool>は>>25の理由で正常にサイズが取得できないから使うな、と
聴いたことがあるんだけど…
ビットセットはそのままstd::bitsetじゃダメなん?

28 :デフォルトの名無しさん:04/12/28 05:36:11
>>25
Effective STL第18項。
std::vector<bool>はコンテナの要件を満たしていない。
それよりもboost::dynamic_bitsetの方がまだましだろ。

29 :デフォルトの名無しさん:04/12/28 05:39:13
stringだとか<<だとか使い始めて気になるといえば、
c言語時代のprintf可変調引数って便利だったなと。
%05dで0つめてくれたり。%08xで16進表記してくれたり。
.printf()というか.vsprintf()に相当するユーティってありそうだけど
見たことない。ご存知のかたいますー?


30 :デフォルトの名無しさん:04/12/28 05:40:13
boost::format

31 :デフォルトの名無しさん:04/12/28 05:41:20
>const参照なら戻り値最適化をしてくれる可能性がさらに高まる。
あー、そうかそうか。大抵の用途は確かに結果受け取りの
const参照で済むから、これからはこまめにconstつけてこうかな。




32 :デフォルトの名無しさん:04/12/28 05:42:46
>>29
そんなに標準の書式マニピュレータを使うのが面倒か。
std::setw()以外は効果がストリームに残ったままになってしまうので元に戻すのが
面倒と言えば面倒だが。
直接フラグをsetf()/unsetf()でいじってもいいしな。

33 :デフォルトの名無しさん:04/12/28 05:43:10
結構、みなさんboost使ってるんですね。
自分は使ったこと一度も無い。ものにもよると思うんだけど、
「これないと損するから黙って使え!」というくらい強烈なお奨め
boostモジュールってある?


34 :デフォルトの名無しさん:04/12/28 05:44:46
boost::bind、boost::shared_ptr

35 :デフォルトの名無しさん:04/12/28 05:45:34
boost::lambda (かなりコンパイラを選ぶ)

36 :デフォルトの名無しさん:04/12/28 05:46:16
boost::regex
手軽に正規表現使うにはいい

37 :デフォルトの名無しさん:04/12/28 05:47:05
boost::mplは基地外のためのライブラリかも。これで書かれたプログラムを見て
発狂しそうになった。

38 :デフォルトの名無しさん:04/12/28 05:50:15
とりあえずスマートポインタを初めとして、
次期標準に入ることが決まってる物は使って損はないと思われ

39 :>>37:04/12/28 05:52:06
template <int leftShifts_, int rightShifts_>
Int_ convert_(Int_ v) const {
return
boost::mpl::if_c <
(rightShifts_ == leftShifts_),
NoShiftPolicy,
boost::mpl::if_c <
(leftShifts_ > rightShifts_),
LeftShiftPolicy<leftShifts_-rightShifts_>,
RightShiftPolicy<rightShifts_-leftShifts_>
>::type
>::type::shift(v);
}

これ、c++のソースなんですか?
意味不明〜


40 :デフォルトの名無しさん:04/12/28 05:54:37
>>次期標準に入ることが決まってる物は使って損はないと思われ

STLくらい標準であれば安心して使えるのだけどねー。
vc++、gccどちらでも同じソースをコンパイルできなければならない仕事を
抱えてるため。

でも次期標準決定してるなら、そろそろ馴れとかねば。


41 :デフォルトの名無しさん:04/12/28 06:02:54
>>40
基本的にはSTLと同じ感覚で使えるので(かゆいところに手が届く感じ)
馴れるというより使ってみればすぐ分かるかと。
(spiritやlambdaは別として)

http://boost.sourceforge.net/regression-logs/
コンパイラの対応状況はここで見れば分かりますが、
VC7.1〜とgccならほぼ全て問題ないと思われ

42 :デフォルトの名無しさん:04/12/28 06:57:32
>>20
関数で危険なのは、ポインタやレファレンスを返すとき。 特に、関数内部で作られたオブジェクトを
ポインタやレファレンスで返すのは重大な誤り。

この場合のオーバーヘッドが気になるなら、shared_ptrを用いるとよい。 shared_ptrを用いれば
Javaのようにオブジェクトを扱えるのでメモリ管理を気にしなくてよい。 ただし、構文が少し
煩雑になるという欠点を持つ。 *や->演算子を多用するから。

例:
typedef vector<string> VectorString;
typedef shared_ptr<VectorString> RefVectorString;

RefVectorString v(new VectorString());
v->push_back("Hello");
VectorString::iterator it = v->begin();
cout << *it;

RefVectorString f(){
RefVectorString v(new VectorString());
v->push_back("Hello");
return v;
}

RefVectorString v2 = f();
もOK!

43 :デフォルトの名無しさん:04/12/28 08:53:41
鬱だ… STL

44 :デフォルトの名無しさん:04/12/28 09:01:45
>>42
お前みたいな初心者が出てくると、かえって混乱するから引っ込んでてくれ。

45 :デフォルトの名無しさん:04/12/31 00:44:35
>20 >42
基本的にはどこかで作ったvector<string>を「丸ごとコピーして」
値返しするんじゃない?
なので、スタックに積まれたvector<string>でも、戻り値は
「丸ごとコピーした」値なので、ローカルスコープを抜けて
元のvector<string>が削除されても戻り値に影響しないはず。

>26
そんな無茶なRVOあるの?

>33
boost::test
CPPUnitよりセットアップが簡単。ガリガリ手書きする必要あるけどね。

46 :デフォルトの名無しさん:05/01/03 14:07:37
المغاربيعلىخالتاريخية
خصصةلمنالرأي كانتص
العاهلالمغربيلموريتانيا،ولكنل


47 :デフォルトの名無しさん:05/01/06 02:25:53
>>15
boost-sandboxにあるBoost.Moveとかも見てみたら良いかも知れませんよ.
実体返しと構文一緒で効率は参照渡し並で(゚д゚)ウマーみたいな.
"Move"の概念がイマイチ浸透してないのとドキュメントが未整備なために
非常に取っ付きにくいライブラリですけれど.

>45
>boost::test
bjamのunit-testルールと組み合わせるとbjamと打つだけで
ビルド後即単体テストな感じでさらに(゚д゚)ウマー.

48 :デフォルトの名無しさん:05/01/08 13:43:06
>>46
だったら、一辺OCAMLやHaskellかじってみたらジェネリックプログラミング
ってなにかよく理解できるとおもうよ

49 :デフォルトの名無しさん:05/01/09 15:23:55
例えばboostのスマートポインタ(shared_ptr)を使うことにした場合、プロジェクト全体で使うように
統一する?
それとも複数箇所から参照されるようなオブジェクトだけにしておく?

50 :デフォルトの名無しさん:05/01/09 17:33:14
統一しておかないと、そのうち同一プロジェクト内に複数の
リファレンスカウンティングスマートポインタが蔓延する罠。

51 :デフォルトの名無しさん:05/01/09 21:00:46
その場合、生ポインタも禁止?

52 :デフォルトの名無しさん:05/03/12 08:13:25
std::getline(std::basic_stringを引数に取るもの)も上限指定できないから、
無茶苦茶行数の長いテキストを読み込ませるなんて攻撃ができる。
なんて話をこの前C++スレで見かけたな。

53 :デフォルトの名無しさん:05/03/12 08:57:47
見かけるもなにも有名な話なんで

54 :デフォルトの名無しさん:05/03/12 21:22:24
今時basic_stringがCOWなSTLってあるんですか?

55 :デフォルトの名無しさん:05/03/13 19:15:08
>>52-53
ぐぐっても見つからない。ほんとに有名な話なのか?

16 KB
■ このスレッドは過去ログ倉庫に格納されています

★スマホ版★ 掲示板に戻る 全部 前100 次100 最新50

read.cgi ver 05.04.00 2017/10/04 Walang Kapalit ★
FOX ★ DSO(Dynamic Shared Object)