【C++】STL(Standard ..
[2ch|▼Menu]
49:デフォルトの名無しさん
08/02/28 14:00:01
thx>>47
>ストリームバッファクラス

あ、これ未調査だった。
やっぱ、ストリームの基底クラスがあるんだね。
それが分かれば分かる筈。

50:デフォルトの名無しさん
08/02/28 14:03:23
>>49
ストリームクラスの基底クラスではない。
継承関係にはない。
ストリームバッファクラス(basic_streambuf<>)のオブジェクトへの
ポインタを保持している。

51:デフォルトの名無しさん
08/02/28 14:29:38
テキスト版は出来ますた。

//---------------------------------------------------------------------------
bool Test::LoadFromFile(const char *filepath, bool bAdd)
{
ifstream fs(filepath);
string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>());

//stringからバッファへロード
}
//---------------------------------------------------------------------------
bool Test::SaveToFile(const char *filepath)
{
string SBuf(Text());

//バッファからstringへセーブ

ofstream fs(filepath);
copy(SBuf.begin(), SBuf.end(), ostreambuf_iterator<char>(fs));
}
//---------------------------------------------------------------------------


52:デフォルトの名無しさん
08/02/28 14:52:45
>>51
ファイルのオープンに成功したかどうかは
チェックせんの?

53:デフォルトの名無しさん
08/02/28 15:02:08
伸びてると思ったらまた宿題の続きかよ

54:デフォルトの名無しさん
08/02/28 15:05:56
>ファイルのオープン

//---------------------------------------------------------------------------
bool Test::LoadFromFile(const char *filepath, bool bAdd)
{
ifstream fs(filepath);
string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>());

if (!fs.is_open()) return false;

//stringからバッファへロード

if (fs.bad()) return false;
if (fs.fail()) return false;

return true;
}
//---------------------------------------------------------------------------


55:デフォルトの名無しさん
08/02/28 15:06:46
あ、やっぱこう。

//---------------------------------------------------------------------------
bool Test::LoadFromFile(const char *filepath, bool bAdd)
{
ifstream fs(filepath);
string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>());

if (!fs.is_open()) return false;

if (fs.bad()) return false;
if (fs.fail()) return false;

//stringからバッファへロード

return true;
}
//---------------------------------------------------------------------------


56:デフォルトの名無しさん
08/02/28 15:10:29
少しはマニュアル読め
コード読んでるこっちが恥ずかしくなるわ

57:デフォルトの名無しさん
08/02/28 15:10:42
if(!fs)

でいいだろ

58:デフォルトの名無しさん
08/02/28 15:14:02
ラジャ!

//---------------------------------------------------------------------------
bool Test::LoadFromFile(const char *filepath, bool bAdd)
{
ifstream fs(filepath);
if (!fs) return false;

string SBuf((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>());

if (fs.bad()) return false;
if (fs.fail()) return false;

//stringからバッファへロード

return true;
}
//---------------------------------------------------------------------------

59:デフォルトの名無しさん
08/02/28 15:30:28
やっぱ、バイナリの場合、書き方分かりません。

既に、
>vector<char> Memory
ってのが存在していた場合は、
上の書き方のままだったらロードするときのメモリは別にとって、次に、Memoryにコピーしなきゃならないのでしょうか?

それだと、メモリ2倍で勿体ないような。

60:デフォルトの名無しさん
08/02/28 15:41:00
>>59
vectorに読み込みたいのか?
ならvectorにも同様のコンストラクタがある。


61:59
08/02/28 15:48:05
あ、そうではなくて、既に存在しているvectorにロードしたい場合は、ですが。

もしかして、
>vector::swap
でおk?

62:デフォルトの名無しさん
08/02/28 15:55:06
>>61
assign では駄目なのか?
なんか基本があやしいふいんきだから
Accelerated C++ くらいは目を通した方がいいと思うんだが。

63:デフォルトの名無しさん
08/02/28 16:02:10
>>61
Memory.assign((istreambuf_iterator<char>(fs)), istreambuf_iterator<char>());
vector<char>(Memory).swap(Memory);

64:59
08/02/28 16:05:38
>>62
ふいんきでヴぁれました?

>>63
回答サンks。
上の1行で良いように見えますが、上下2行でセットですか?

まずは、assignぐぐってみまつ。

65:デフォルトの名無しさん
08/02/28 16:11:15
この内容って関係してますか?
URLリンク(etwas.wolfish.org)

66:デフォルトの名無しさん
08/02/28 16:58:38
チャットじゃないんだから少し頭ん中整理してから投下してくれ

67:デフォルトの名無しさん
08/02/28 17:04:43
>>59
おまえ C++Builderスレでも同じ様なこと書いてる奴だろ?

68:デフォルトの名無しさん
08/02/28 17:04:59
バイナリの方、整理しますた。
//---------------------------------------------------------------------------
クラスヘッダー: std::vector<char> Memory;
//---------------------------------------------------------------------------
bool Bin::LoadFromFile(const char *filepath, bool bAdd)
{
ifstream fs(filepath, std::ios::in | std::ios::binary);
if (!fs) return false;

fs.seekg(0, std::ifstream::end);
Memory.resize(fs.tellg());
fs.seekg(0, std::istream::beg);
if (fs.bad()) return false;
if (fs.fail()) return false;

fs.read(&Memory[0], Memory.size());
fs.close();
return true;
}
//---------------------------------------------------------------------------
bool Bin::SaveToFile(const char *filepath)
{
ofstream fs(filepath, std::ios::out | std::ios::binary);
if (!fs) return false;

copy(Memory.begin(), Memory.end(), ostreambuf_iterator<char>(fs));
if (fs.bad()) return false;
if (fs.fail()) return false;

return true;
}
//---------------------------------------------------------------------------

69:59
08/02/28 17:06:08
>>67
自分もそう思ったが、よくよく見ると違った。ていうか、あっちの方がラベルが高くて難しい単語が出てくるおw

70:デフォルトの名無しさん
08/02/28 17:12:44
鼻血ブーーーーーーーーーーーーーーーーーーー
うんこブリブリブリーーーーーーーーーーーーー

71:デフォルトの名無しさん
08/02/28 18:11:16
>>69
いや、それじゃねえな。 偶々std::を使ったレスを持ち出して、 話のはぐらかしか?

72:デフォルトの名無しさん
08/02/28 18:19:14
イミフメ>>71


URLリンク(articles.blog79.fc2.com)
>std::stringの大文字/小文字変換
>通常は上記の書き方で問題ありませんが、これがコンパイルエラーとなる場合があります。

についてkwskキボンorz

73:デフォルトの名無しさん
08/02/28 18:24:42
>>72
解説文も解読できないんならおまえ向いてないよ。 工場のライン工やっとけ

74:デフォルトの名無しさん
08/02/28 18:30:01
のびてると思ったら…
C++って学校の宿題スレなかったっけ?

75:デフォルトの名無しさん
08/02/28 18:31:09
>int toupper(int);
>int tolower(int);
> std::transform(str.begin(),str.end(),str.begin(),toupper);
>: error: no matching function for call to 'transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unknown type>)'

これでもエラー出るんですよねorz

76:デフォルトの名無しさん
08/02/28 18:34:38
ゴメンなさい、
> (int (*)(int))std::toupper
に直してませんですたorz

77:デフォルトの名無しさん
08/02/28 20:57:33
マクロの場合があるからと違うんか

78:デフォルトの名無しさん
08/02/28 22:13:46
>>77
違う。localeを引数に取る多重定義があって、それと曖昧と言われてしまうため。

79:デフォルトの名無しさん
08/02/28 23:29:51
関数オブジェクトを使うべき

80:デフォルトの名無しさん
08/02/29 05:46:31
typedef std::map<char, void*> MyMAP //void* にはMyMAPのポインタが入る

このようにmapに自分と同じ型を含めたい場合は、どう書くのがスタンダードでしょうか?
今はnewで確保して入れて、(MyMAP*)にキャストして使用&deleteしてるんですが。

81:デフォルトの名無しさん
08/02/29 09:43:26
>>80
typedef だと無理っぽいねぇ。 class で囲ってやるか、意味的に奇怪だけど継承するとか。
struct MyMap : std::map<char, MyMap*> {};

82:デフォルトの名無しさん
08/02/29 10:15:18
今、軽く衝撃を受けたわ

83:デフォルトの名無しさん
08/02/29 10:32:04
>>81
>struct MyMap : std::map<char, MyMap*> {};
そんな事ができるとは思いもしなかった

84:デフォルトの名無しさん
08/02/29 10:42:27
>>83
できない理由が無ければできるもんだよ。

85:デフォルトの名無しさん
08/02/29 11:08:07
例えば、vectorってベクターって呼んで、vectorクラスなんて呼ばないけど、
STLってできあがるものってクラスなんだね。

86:デフォルトの名無しさん
08/02/29 11:14:36
>>85
いいえ。コンテナだけがSTLではありません。

87:デフォルトの名無しさん
08/02/29 11:17:57
え”?

STL = コンテナ ∩ イテレーター ∩ ?

88:デフォルトの名無しさん
08/02/29 11:23:47
つ[<algorithm>, <numeric>, ...]

89:デフォルトの名無しさん
08/02/29 11:25:34
>[<algorithm>, <numeric>, ...]

こういうのって何て呼ぶんだ?
インライン関数群?

90:デフォルトの名無しさん
08/02/29 11:45:02
なぜ何でもカテゴライズしたがるんだか

91:デフォルトの名無しさん
08/02/29 11:51:26
>>89
インクルードファイルalgorithmやnumericで定義されている関数

>>90
日本人だからでしょ

92:デフォルトの名無しさん
08/02/29 12:09:35
テンプレートだけに型に(ry

93:デフォルトの名無しさん
08/02/29 12:52:10
boost::type_traits早く標準化汁

94:デフォルトの名無しさん
08/02/29 15:59:45
標準アルゴリズムって言葉使わないか?

95:デフォルトの名無しさん
08/02/29 17:22:11
いやまて朝鮮人かもしれんぞ
ことによると中国人かも

96:デフォルトの名無しさん
08/02/29 17:56:00
>>90
神の教えだからだろ

97:デフォルトの名無しさん
08/02/29 18:34:41
std::wstringに入ってるファイル名があるのですが、
ここから拡張子だけを抽出したい場合、定番の方法などあるのでしょうか?

98:デフォルトの名無しさん
08/02/29 18:50:10
rfind と substr でいけるんじゃね?
まあ c_str と _splitpath() のほうが面倒が少ないと思うけど。

99:デフォルトの名無しさん
08/03/01 13:02:13
Win32APIが使えるなら一発

100:デフォルトの名無しさん
08/03/03 16:27:08
>>97
std::stringにファイル名が入ってるなら
そのファイル名が入ってるstd::string型のオブジェクト名
がfilenameという名前とすると
char *fname = filename.c_str();
てな感じでchar *型で受け取り
#include <cstring>をインクルードしておき
char *piliod = strrchr(fname,'.');
で拡張子の手前のピリオド位置を取得し
piliod++;ってすれば拡張子名だけchar *型で取得できる
これらの操作をwchar_t用の関数に変更すれば
wchar_t *型で拡張子名を取得できる
まぁ、STL板だしstd::wstringを操作するとしたなら
素直にクラスのfind_last_of使って
sizetype pos = filename.find_last_of(L'.')てな感じで
けつからピリオドの位置見つけてpos++;して
std::wstring fextenshion =filename.substr(pos)とすれば
拡張子だけ手に入る


101:デフォルトの名無しさん
08/03/03 18:54:54
が、特殊ケースを想定するとそれだけでは済まないので、
ちまちま書くよりc_strでランタイムやAPIの既存のルーチンに任せるのが定番。

102:デフォルトの名無しさん
08/03/03 18:57:59
だよなぁ。hoge\2007.11.10\bar とか。

103:デフォルトの名無しさん
08/03/06 14:54:51
>std::vector<char> resultBuf;
から、
>std::string SBuf;
にデータを移すにはどう記述したら良いですか?

SBuf = resultBuf;

とするとコンパイルエラーです。

インテリセンスの無い環境でやっててつらいです。

104:デフォルトの名無しさん
08/03/06 15:12:55
>>100
char *fname = filename.c_str();
これは、不味いんじゃないのか?


105:デフォルトの名無しさん
08/03/06 15:15:26
>>103
SBuf = &resultBuf[0];

106:103
08/03/06 15:20:33
>>105
有難うございます。コンパイル通りました。


ついでですが、resutlBufにNULLが入ってる場合、どう書けば良いですか?
今回不要なんですが。
memcpy使うのもC言語っぽいしぃ。

107:デフォルトの名無しさん
08/03/06 15:21:39
std::string SBuf(resultBuf.begin(), resultBuf.end());
または、
SBuf.assign(resultBuf.begin(), resultBuf.end());
resultBufがnull終端なら>>105でもいい

108:デフォルトの名無しさん
08/03/06 15:24:40
>>105
stringの内部バッファの連続性はまだ保証されてない気がしたが。

109:デフォルトの名無しさん
08/03/06 15:27:58
>>108
それは関係ないだろ
string s = "foo";
とかやるのと一緒

110:デフォルトの名無しさん
08/03/06 15:31:41
>>108
resultBufは、char型のvector
vectorはバッファの連続性を保証されているから無問題
問題があるとすれば、>>107の指摘の様にnull終端では無い場合

111:103
08/03/06 15:42:13
NULL入りの場合、無しの場合、両方分かりました。
ありがとうございましたorz

112:デフォルトの名無しさん
08/03/06 15:52:55
>>108
それよりも、>>104の指摘している
>>100
char *fname = filename.c_str();
の方がやばいんじゃない?
*fnameの代入が終了したら、c_str()の戻したポインタの有効期限が切れているから

char *piliod = strrchr(fname,'.');
の処理をするときには、何が起こるのか判らない状態になっていると思うんだけど


113:デフォルトの名無しさん
08/03/06 16:06:11
>>112
filename.c_str()で返るポインタは、filenameの非constメンバ関数が呼ばれるまで有効

114:デフォルトの名無しさん
08/03/06 16:27:45
>>105だとresultBufが空のときにまずいような気がする

115:デフォルトの名無しさん
08/03/06 16:31:54
null終端なら空ってことはありえない

116:デフォルトの名無しさん
08/03/06 16:43:22
>>113
お前そんなプログラム書いてるのか。お前には仕事を任せられんな。

117:デフォルトの名無しさん
08/03/06 16:44:44
>>113
まじ?
ゴミになったのに、ゴミになったって気が付いてないとかそう言う問題の気がするが...

lstrcpy(buf, str.c_str());
これは怖くないが

char *word = str.c_str();
lstrcpy(buf, word);
これは、いつ見ても、ヤバイ香りがするんだ

関数の返すポインタには何度も煮え湯を飲まされたし...orz

118:デフォルトの名無しさん
08/03/06 16:52:12
>>116
>>117

>>113 is right.

About c_str()

The return value is valid only as long as the string exists, and as long as only
constant functions are called for it.



119:デフォルトの名無しさん
08/03/06 16:53:25
>>118
言い訳はいいからお前には仕事はやらん。

120:デフォルトの名無しさん
08/03/06 16:54:49
>>116
お前のレスだけ明後日の方向むいててワラタ

121:デフォルトの名無しさん
08/03/06 16:56:16
>>116
「そんなプログラム」ってどんなプログラム?
>>113はプログラムの書き方なんか一言も触れてないよね。
c_str()の戻り値の寿命についての情報を書いてるだけ。

「そんなプログラム」ってどんなプログラム?
それは113のどこに書いてあるの? 教えて。

122:デフォルトの名無しさん
08/03/06 17:05:37
煽ってるようだけどその手には乗らないよ。
びびりまくりでワロタw

123:デフォルトの名無しさん
08/03/06 17:08:15
ちゃんと寿命を理解しないで使う方が怖いよ

124:デフォルトの名無しさん
08/03/06 17:09:05
仕様をちゃんと知らずに見よう見まねでライブラリを使う人ってのは結構いるだろうけど、
見よう見まねや雑談で得た俺仕様を根拠にして、正しい仕様に基づく使い方を攻撃するのは
みっともないと思う。

125:デフォルトの名無しさん
08/03/06 17:10:03
うっかり誰かがstring書き換えるコードを途中に入れてしまったら、
なんて心配をするようなら、116の言うことだって分からなくもない。

126:デフォルトの名無しさん
08/03/06 17:11:55
どうでもいいが、
>lstrcpy(buf, str.c_str());
これと
>char *word = str.c_str();
>lstrcpy(buf, word);
これで振る舞いが異るようにc_strを実装する方法は存在しないだろ

127:デフォルトの名無しさん
08/03/06 17:11:59
>>117
>関数の返すポインタには何度も煮え湯を飲まされたし...orz

仕様を確認せずに「香り」でコード書くから何度もそういうミスを繰り返すのかもね

128:デフォルトの名無しさん
08/03/06 17:15:34
仕様仕様言ってて仕事がもらえない方が悲惨だと思わない?
会社にはその会社の流儀って物があってね。

129:デフォルトの名無しさん
08/03/06 17:17:33
>>126
>lstrcpy(buf, str.c_str());
は、lstrcpyの処理が終わるまで、誰もstrを変更しないことが保証されている。

>char *word = str.c_str();
>lstrcpy(buf, word);
は、どこかの禿が
>char *word = str.c_str();
>f(str);
>lstrcpy(buf, word);
と変更しない保証は何処にもないし、f(str)がstrを変更しない保証も無い

130:デフォルトの名無しさん
08/03/06 17:18:24
んでその流儀に従って何度も煮え湯を飲まされるわけ?
なんかバカらしいぞそれ。

仕様をよく確認しなかったが、流儀に従って安全そうに書いたので
救われたって話ならわかるけど。


131:デフォルトの名無しさん
08/03/06 17:19:54
まったく、ひどい論点のすり替えだぜ。

132:デフォルトの名無しさん
08/03/06 17:21:09
>>130
お前ニートか無職だろ。
協調性がゼロみたいだもん。

133:デフォルトの名無しさん
08/03/06 17:22:30
>>129
そんな話はしてねーよ
前者と後者で振る舞いが異なるはずがないと言ってるだけ

134:デフォルトの名無しさん
08/03/06 17:24:38
いや個々の会社が>>100みたいなのを禁止するのは勝手だけども、
>>100みたいな使い方が仕様に照らして問題ないという事実は変わらないだろ

135:デフォルトの名無しさん
08/03/06 17:25:44
>>132
ちゃんと働いてるし、給料も沢山もらってるから心配スンナ
世の中はそんな妙な流儀を押し付けられるような職場ばかりじゃないってこと

136:デフォルトの名無しさん
08/03/06 17:35:32
未経験高卒ですがC++で仕事したいです

137:デフォルトの名無しさん
08/03/06 17:44:28
>>133
それはわかる。
ただ、俺から見れば117がやばい香りを感じるのは
129のような可能性があるからというのが最大の理由ではないかと思う。

138:デフォルトの名無しさん
08/03/06 17:50:14
>>137
全く持って同意

同一データに、2通りのアクセス方法があると、間違いを起こす元になると思う


139:デフォルトの名無しさん
08/03/06 17:54:50
>>137
なるほど、そういう見方もあるか
俺は、>>117がC++の実行モデルをあやふやにしか理解してないとか、
文を跨ぐと一時オブジェクトの寿命が切れるのと混同してるとか、そんなのを想像してた
それに、「ゴミになったのに」云々言ってるから、そのままのコードでもポインタが無効になるのを危惧しているように読める

140:デフォルトの名無しさん
08/03/06 17:57:27
イテレータだって挿入削除で無効になるんだから、
特別神経質になるほどのことでもないと思う。

141:デフォルトの名無しさん
08/03/06 17:57:30
>>138
そういう意味では、イテレータも基のstringがconstでない場合は、
おちおち使っていられないよな。

例えばだけど、本質的にはこの2つに違いはないと思った。
(もちろん文字列中に\0はないとして)
char const* p = std::strchr(s.c_str(), 'a');
std::string::const_iterator it = s.find('a');

142:デフォルトの名無しさん
08/03/06 18:05:16
赤福の賞味期限偽装に近い問題やね

賞味期限はいつか本当に切れるだろうが、それは今じゃない...

143:108
08/03/06 18:06:14
resultBufがstringだと勘違いしてた

144:デフォルトの名無しさん
08/03/06 18:19:31
今更だなw
だが正直でよろしい

145:デフォルトの名無しさん
08/03/06 18:49:07
>>116はどう見ても釣り。


146:デフォルトの名無しさん
08/03/06 19:24:41
>>116は真性の馬鹿者
仕様を初めて知って、これからはいかにも前から知ってましたよって顔で
他の人にこの問題を説明するだろう。

147:デフォルトの名無しさん
08/03/06 19:25:38
>>146
このスレではどうでもいいことだけどな。

148:デフォルトの名無しさん
08/03/06 20:54:34
ところでc_str()をchar*に入れてるのは誰も突っ込まないんだろうか。

149:デフォルトの名無しさん
08/03/06 21:03:52
確かに、そういう人には仕事任せたくないなw

150:デフォルトの名無しさん
08/03/06 21:07:44
それ以前にコンパイルエラーになると思うが

151:デフォルトの名無しさん
08/03/06 21:11:41
std:stringのバッファの連続性が保証されることは、&str[0]とstr.c_str()のアドレス同一性を保証しますか?

152:デフォルトの名無しさん
08/03/06 21:15:31
保証しない。
c.str を呼んだ場合、メモリの最確保が行われる可能性がある。

153:デフォルトの名無しさん
08/03/06 21:17:32
なるほど。str.data()はどうでしょうか。

154:デフォルトの名無しさん
08/03/06 21:19:05
残念ながら data も同じ。

155:デフォルトの名無しさん
08/03/06 21:22:21
しかしなんだな。
今の規格ではバッファの連続性を保証していなくて、
次の規格ではバッファの連続性を保証する予定ではあるのだが、
連続性を保証したら data で参照、ポインタ、イテレータが失効する可能性は
もう無くなるとしてもいいような気がするんだけど、
最新のドラフトではそうなってないんだよな。
ミスなのか、それとも何か深い理由でもあるのか・・・。

156:デフォルトの名無しさん
08/03/06 21:25:17
>>155
正直プライオリティ低いんだろ
どうでもいいわと思ってる委員が多いと予想

157:デフォルトの名無しさん
08/03/06 21:26:44
しかし、そろそろそういう細かいところも詰めていかないと、
0x の x は16進数ってのもあながち冗談では済まなく・・・。

158:デフォルトの名無しさん
08/03/06 21:28:14
いざとなったら得意のundefined behaviorでいいだろ。

159:デフォルトの名無しさん
08/03/06 21:51:10
やたらスレが伸びてると思ったら・・・
もうここの連中には仕事任せられんな
今後は>>170にすべてを託すこととする
なお異論は受け付けない

160:デフォルトの名無しさん
08/03/07 04:52:01
それは無意味にkskしろってことかい

161:デフォルトの名無しさん
08/03/07 09:34:55
string::swap について教えて下さい。

>void func(string &sArg)
> string sBuf = "AAAAAA";
> sBuf.swap(sArg);

のときって、sBufの内容がsArgに移し変えられるっていうのがswapの機能だと思います。

この場合、実装に依存するんだと思いますが、
メモリのエリアがガバっとコピーされるのではなくてクラスの参照を交換してくれるんでしょうか?
性能的に優れてるものだったら、使いまくりたいですし。

一度も使ったこと無いので、swap後にちゃんとメモリ保持しててくれるんだろうか、
落とし穴は無いだろーななんてガクブルしてます。

162:デフォルトの名無しさん
08/03/07 09:55:42
>>161
stringだったら、内部で保持しているであろう
文字列へのポインタや長さなどといった変数だけが交換されるとみな仮定している。

一般的に、swapは例外を投げないとされており、
しかも、std::stringのswapはO(1)と規格で定められている。
だから、文字列の中身まで交換する実装はありえない。

163:161
08/03/07 10:29:50
サンクス。

>一般的に、swapは例外を投げないとされており、

へぇー、勉強になりました。

>しかも、std::stringのswapはO(1)と規格で定められている。

勉強になりましたが、O(1)って何だ?_?

>だから、文字列の中身まで交換する実装はありえない。

あ、そうなんですか?
例外を発生できないとなると、参照を交換する以外に実装無いと思うんですが。
だって、交換じゃなくてコピーならば、メモリを確保しないといけないし、そうなるとエラーが発生する可能性があるような。
って素人なのに生意気逝ってすみません。

164:デフォルトの名無しさん
08/03/07 10:37:30
O(1)というのは、例え文字列が長くてもswapが一定時間で終わらなければならないってこと。
文字列をコピーするなら、文字列が長くなればそれだけコピーに時間が掛かるから、この制限を満たせない。
詳しくは「計算量」でググれ。

>例外を発生できないとなると、参照を交換する以外に実装無いと思うんですが。
まさに>>162はそう言ってるんだと思うよ。
中身をコピーして交換するんじゃなくて参照(具体的にはポインタ)を交換する。

165:161
08/03/07 10:40:31
ラジャ!

>文字列の中身まで交換する実装はありえない。

つまり、中身をコピーする実装はありえない、って文章ですね。
で、そう言い切れる理由はO(1)で時間制限してて、”ま、参照を交換する実装にしる!”、っていわば指令が出てるわけですね。

166:デフォルトの名無しさん
08/03/07 10:58:42
>>165
deep copyをするとno throwの保障ができなくなる。

167:161
08/03/07 11:00:02
すみません、教えてクンですみませんが、最後に記述を教えて下さいorz

swapを使いまくりたくなりました。
vector<char>とstringの間で、swapする記述はありますでしょか?

vectorメモリは連続しているので、vector同士だとswapできるんじゃないかと思ったのですが。
直にメモリアクセス?イテレータンを無視し過ぎるのも良くないとは思わないでも無いですが。

168:デフォルトの名無しさん
08/03/07 11:07:45
>vector<char>とstringの間で、swapする記述はありますでしょか?
ない。実装上も、例えばstringがnull終端の分だけ余計に内部バッファを持っているなら無理。

>vectorメモリは連続しているので、vector同士だとswapできるんじゃないかと思ったのですが。
vector同士ならできる。

169:161
08/03/07 11:09:58
>ない。実装上も、例えばstringがnull終端の分だけ余計に内部バッファを持っているなら無理。

なるほど。納得。下手にやるとはまりますね。

>vector同士ならできる。

vectorの異なる構造体同士でもできますか?
記述例超キボンw

170:デフォルトの名無しさん
08/03/07 11:19:32
テンプレートパラメータが違うとダメだろう

171:デフォルトの名無しさん
08/03/07 11:28:20
記述例もなにも、vとv1が同じ型のvectorなら、
v.swap(v1);
で交換できる。vectorに限らずあらゆるコンテナで。

172:161
08/03/07 11:36:47
全部分かりました。有難うございましたorz


つまり、コンテナが違うとswapはキャストやらなんやらやヴぁい記述になるわけですね(はまるからやらないけど)

173:デフォルトの名無しさん
08/03/07 13:11:25
質問です。

クラスメソッドの引数で、

>method(string s1) { method(s1.c_str()) }
>method(const char *s1);

みたいな感じで、オーバーロードで「string」も「char *」も両方受け入れるようにしてるんですが、
どちらか片方だけ定義、ということにできますでしょうか?

174:173
08/03/07 13:15:17
2つ要るとしたら、stringベースとchar*ベースと効率が良いのはどちらでしょう?
まぁ、大差無いですか?

175:デフォルトの名無しさん
08/03/07 13:20:59
>>173
stringだけ書いとけばconst char*からstringを暗黙に構築してくれると思うが、効率は良くないかも

176:デフォルトの名無しさん
08/03/07 13:37:12
>>173
片方がconst char * なんだから、string const & の方がいいんでないかい?
で、どっちみちstringを受ける方もconst char * 版を呼び出すなら要らないわけで。

177:173
08/03/07 13:37:33
何だ、そうでしたか。無駄に2つ作ってしまったorz

178:173
08/03/07 13:42:12
頭が混乱してましたが、

>stringだけ書いとけば
の場合は、引数が入力である場合は、おk、

>片方がconst char * なんだから、string const & の方がいいんでないかい?
これ(つまり、& )を選択した場合は、2つ書かないといけないんですよね?

コンパイラで試せば良いのですが、皆さん普通はどうされてるのか知りたくて。

179:デフォルトの名無しさん
08/03/07 13:44:52
>>178
わけがわからん。何がしたいのか書きなおしてくれ。

180:173
08/03/07 13:48:53
ごめんなさい、テストプログラム書いたら違っていました。

つまり、
>stringだけ書いとけば
でおk。

>string const & の方がいいんでないかい?
でおk。

但し、char *を渡すと、W8030 Temporary used for parameter のウォーニングが出ると。

181:デフォルトの名無しさん
08/03/07 13:52:35
話を読む限りstringやconst char*である必要性を感じないし、
俺だったら初めと終わりのイテレータを引数に取るようにする。
stringでもconst char*でもないやつもかかってこい。

182:173
08/03/07 13:53:05
あ、「「string &」だとウォーニングだったのが、「string const &」だとウォーニング消えました。

つまりやりたかった、
>string と char *の一本化、
および、
>参照渡しでメモリ節約&コンパイルウォーニング無し
の全て解決しました。orz

183:173
08/03/07 13:54:45
>俺だったら初めと終わりのイテレータを引数に取るようにする。

はつみみです。

これ知っとくと大分楽できそうですね。何が良いのか調べてみます。
(参考サイトでも何でも教えて頂ければ参照します。レスで教えてというのも嫌われそうなので)

184:デフォルトの名無しさん
08/03/07 13:58:47
string const &が要求されてるところにconst char *を渡そうとしたら、stringの一時オブジェクトが作られて、
文字列の内容がコピーされるから、メモリの節約にはなってない

185:173
08/03/07 14:20:17
>>184
あっ、そーですか。
じゃぁ、今まで作った基礎クラスはそのままに2つのままにしておこうかなぁ。。。
悩む。

186:173
08/03/07 14:58:05
今、上記内容に沿って、”string const &型”に全面書き換え中ですが、
以外に頭が固いのが、stream系ですね。
っていうか、ifstreamとか引数にstring受け入れないっぽい。

187:デフォルトの名無しさん
08/03/07 15:26:37
>>186
コードを書く前に、もう少しきちんと勉強したほうがいいと思います。


188:デフォルトの名無しさん
08/03/07 16:40:31
class StringArg
{
const char* p_;
public:
StringArg(const string& str) : p_(str.c_str()) {}
StringArg(const char* str) : p_(str) {}
const char* get_arg() const { return p_; }
};

method(const StringArg& arg);

189:172
08/03/07 16:49:34
>>188
はじめそれに近い形で書いてたんですが(違いはstring側はconstにしてなかったとこだけ)、
メソッド宣言2行になると、以外にクラス部品作るのがしんどくて。
効率悪くても1つにしたいな、と思いました。

で結局、
>StringArg(const string& str)
の方だけ活かして、
巨大なバッファで、かつ、char *の可能性がある場合のみは、188 の通り、
2つ宣言しようかと思っています。

190:デフォルトの名無しさん
08/03/07 16:50:09

172じゃなくて、173でした。

191:デフォルトの名無しさん
08/03/07 16:58:43
>>189
多分お前は>>188を誤読してる
const char *をとるメソッドもconst string &をとるメソッドも用意せずに、
const StringArg &をとるメソッドを用意しろってことだろ

192:デフォルトの名無しさん
08/03/08 09:00:47
void Method(const char*); のみ用意して、
std::stringを渡したい場合は↓じゃあかんのか

std::string s;
Method(s.c_str());

193:デフォルトの名無しさん
08/03/08 20:47:51
#include <set>
using namespace std;

int main()
{
set<int> s;
s.insert(1);
s.insert(4);
(*s.begin()) = 5;
return 0;
}
上のプログラムは違法ですよね?
ウチのコンパイラは文句を言わないんだけどおかしいですよね?


194:デフォルトの名無しさん
08/03/08 20:53:45
>>193
とりあえずg++だとエラーになった

195:デフォルトの名無しさん
08/03/08 20:59:06
ふぁっきんBCC

196:デフォルトの名無しさん
08/03/08 21:03:38
>>193
C++2003 に準拠しているならそれでも規格の範囲内。
変更できないことが明記されるのは次の C++0x から。
URLリンク(www.open-std.org)

コンパイル通るからといっても、まずいことがわかってるなら
やらないでおいたほうがいいね。

197:デフォルトの名無しさん
08/03/08 21:04:28
>>193
Effective STL 第22項をどうぞ。

198:デフォルトの名無しさん
08/03/08 21:12:44
>>196
サンクス。STLってたくさん欠陥があるんですね。

>>197
サンクス。今度立ち読みします。

199:デフォルトの名無しさん
08/03/10 08:45:25
stringにバイナリ書き込みで、
resizeした後、・・・1
c_str()でポインタ取って、・・・2
memcpy・・・3
してます。

2ってSTL的には読み込み専用ポインタであり間違ったコードなんですが、
動作してるのでほっとこうか、正しく書こうか迷ってます。
どうしたら良いでしょう?

200:デフォルトの名無しさん
08/03/10 08:47:18
>>199
間違ったコードを正しく書くのに、何を迷うの?

201:デフォルトの名無しさん
08/03/10 08:50:50
>>199
必要な知識は全部持ってるみたいだが、何を訊きたいんだ?
未定義動作に依存するという欠点よりもそのコードが持つ利点が大きいと考えるなら
それを使い続ければいいし、そうでないなら書き換えればいい

202:デフォルトの名無しさん
08/03/10 08:50:55
いろいろ。

じゃ、直しておきまつ。

203:デフォルトの名無しさん
08/03/10 20:18:13
コンストラクタやassignとかappendがあるもんな。
イテレータにstd::copyでもいけるし。

204:デフォルトの名無しさん
08/03/11 09:05:07
>イテレータにstd::copy

イテレータンって参照するだけじゃないんだ。
イテレータンがメソッド持ってるって考え方がイマイチわかんないんだおね。

205:デフォルトの名無しさん
08/03/11 15:29:40
いや、イテレータを引数に取れる関数だろ

206:デフォルトの名無しさん
08/03/11 19:51:25
イテレータは何かを反復するもの。「何か」は参照かもしれないし、操作かもしれない。

207:デフォルトの名無しさん
08/03/11 20:59:59
ifstreamで半角空白を含むファイル名や、日本語を含むパスで
ifstream ifile(フルパス名);で失敗してしまうのですが、これは仕様なのでしょうか?
仕様なのでしたら回避策はあるのでしょうか?

Visual Studio 2005SP1を使用しています。
よろしくおねがいします。

208:デフォルトの名無しさん
08/03/11 21:05:45
問題が再現する最小限のコードを貼れ。まずはそれからだ。

209:デフォルトの名無しさん
08/03/11 21:05:59
ロケールの設定とか?

210:デフォルトの名無しさん
08/03/11 21:29:37
コンパイルはVisualStudio2005 Command Promptで行いました。


#include <iostream>
#include <fstream>
#include <windows.h>

using namespace std;


int main(int argc, char **argv)
{
ifstream ifile("新規テキスト ドキュメント.txt");
if(ifile) {
MessageBox(NULL, "success", "info", MB_OK);
ifile.close();
} else {
MessageBox(NULL, "failed", "info", MB_OK);
}
return 0;
}

結果はfailedとでます。

211:デフォルトの名無しさん
08/03/11 21:31:17
間違えました。
フルパス名をコピペして、\を一つ減らしてエクスプローラーに貼り付けると正常に開けます。

ifstream ifile("d:\\新規テキスト ドキュメント.txt");


212:デフォルトの名無しさん
08/03/11 21:32:25
まさか、そのファイルがカレントディレクトリに置いてないとか言わないよな?
つーか、このスレより環境依存OKのスレかWindows関連のスレの方がいい希ガス。

213:デフォルトの名無しさん
08/03/11 21:42:30
ありがとうございます。
環境依存スレに行ってみます。

214:デフォルトの名無しさん
08/03/12 03:34:34
vectorに要素をpush_backするとき、全ての要素がこっそりと引越し、
要素を指していたポインタが無効になり、ひどい目にあうことが
あるということを知りました。

そこで質問なのですが、引越し時の要素のコピーは
コピーコンストラクタを使って行われるのでしょうか?
それとも単純にmemcpyなどで行われるのでしょうか?

215:デフォルトの名無しさん
08/03/12 04:23:23
>>214
コピーコンストラクタじゃなきゃヤバイでしょ。
あくまで例だけど、int型のメンバxと、そのアドレスを持つint*型のメンバpxがあって、
pxの値をmemcpyなんかした日にはえらいこっちゃ。

216:デフォルトの名無しさん
08/03/12 07:50:53
>>214
もすこし具体的にどうぞ。

>>215
あんたも何を言いたいんだか。

217:デフォルトの名無しさん
08/03/12 07:51:34
コピーコンストラクタでpxをdeep copyしてなければ同じようにえらいこっちゃ。だけどね。

218:デフォルトの名無しさん
08/03/12 07:53:22
>>217
それは別問題

219:デフォルトの名無しさん
08/03/12 07:56:14
>>214
再割り当て時にはコピーコンストラクタが使われるよ。

220:デフォルトの名無しさん
08/03/12 07:57:26
>>216
俺は第三者だけど、>>214が何を訊きたいかは分かるし、>>215の回答も理解できるよ。
>>215は当を得た回答だと思う。

221:217
08/03/12 08:01:58
deep copy するわけじゃないのか。215が言いたいのは。
コピーコンストラクタでpx=&xが必要ってことだな。多分。

222:デフォルトの名無しさん
08/03/12 08:06:43
STLはコピーを前提に作られている。そういうもの。

223:デフォルトの名無しさん
08/03/12 08:07:42
>>214
要素は引っ越しません。

224:デフォルトの名無しさん
08/03/12 08:46:07
>>221
コピーコンストラクタという言葉を使っているところからして、
ユーザー定義型がvectorにどう扱われるかを訊きたがってるんだろうな、と判断した上で、
「コピーコンストラクタを用いなければ"正しく"コピーできない型があり得るのに、
vectorが内部で勝手にmemcpyによるコピーで満足しちゃうなんてことは無いよ」
って回答した次第。

225:デフォルトの名無しさん
08/03/12 08:49:23
>>223
嘘をつくな

226:デフォルトの名無しさん
08/03/12 08:50:39
>>223
規格に"引っ越し"という言葉は書いてないという揚げ足をとってるのか?
それとも単にC++を知らないだけ?

227:217
08/03/12 09:01:52
I got it.

関係ないけどクラスをmemcpy、memcpyするソースをよく見かける。怖くて仕方ない。

228:217
08/03/12 09:02:25
memset、memcpyだった。

229:デフォルトの名無しさん
08/03/12 09:03:13
怖いじゃなくて、memsetだとプログラム落ちるだろ、jk

230:デフォルトの名無しさん
08/03/12 09:05:39
そういうのはCのノリが抜け切れてない年寄りが多いの?

231:217
08/03/12 09:15:12
>>229
落ちるとは限らないよ。仮想関数がないクラスではうまくいく。(memsetでセットする値が適切なら)

仮想関数があるクラスでmemset(this,0,sizeof(this))とかやると
仮想関数ポインタが0になるので、
ポリモーフィズム使用時にNULLポインタアクセスで落ちた。

だから抽象クラスにしたいときには、memsetしてないか全部チェックせなあかんかった。

>>230
そうだね。特に組込系が多いね。クラスを構造体の延長として使ってる。

232:217
08/03/12 09:22:43
URLリンク(sunlight.cocolog-nifty.com)

こういう変なことする人もいる。class S が 仮想関数を持つクラスをメンバ変数に持ってたら
ダメじゃんって突っ込みたい。

スレ違いでゴメン!

233:デフォルトの名無しさん
08/03/12 09:28:30
突っ込みたいなら突っ込んであげればいいのに

234:デフォルトの名無しさん
08/03/12 10:05:25
>>232
君がインストラクタになってあげなさい

235:デフォルトの名無しさん
08/03/12 12:47:55
引っ越しって言えば、moveだろ。
copyを引っ越しと言うのは無理があり過ぎる。

236:デフォルトの名無しさん
08/03/12 12:49:21
>>235
引越しは後片付けしてから出て行くよ。

237:217
08/03/12 15:43:34
自分は暗黙のインストラクタでいいのでw

238:デフォルトの名無しさん
08/03/12 21:05:27
>>235
「copyを引っ越しと言」ってるようには見えないよ。「引越し時の要素のコピー」って書いてある。

コンピュータデータのmoveは、実際には「copyする」ことと「元を削除する」ことで成り立っているわけで、
つまり「move(ここではvectorの要素の再配置のこと)の手段としてのcopy」の表現だろう。

239:デフォルトの名無しさん
08/03/12 21:28:37
コピコンでは普通は deep copy する。
そういうもの。

240:デフォルトの名無しさん
08/03/12 22:56:24
参照カウント付きハンドルの場合はそうじゃないけど。
(boost::shared_ptr etc)

241:デフォルトの名無しさん
08/03/12 23:00:16
それは特殊例

242:デフォルトの名無しさん
08/03/14 00:11:29
インストラクタwww

243:214
08/03/14 01:02:08
レス遅れてすみません。解答してくださったみなさん、
ありがとうございます。

でも、*ほとんどの* ケースでは、単純なmemcpyで済みそうなのに、
いつでもコピーコンストラクタが使われるという仕様に疑問を感じます。

コピーコンストラクタが使われるとなると、コピー元のオブジェクトに
対してデストラクタを呼び出す必要があります。これは、*ほとんどの*
ケースでは全く馬鹿馬鹿しい無駄です。

それならreserve使え、とおっしゃるかもしれませんが、どれだけの
領域をreserveしておけばいいのか、前もって計算できないことも
よくあります。

引越し時のコピーはmemcpyで行われるべきではないでしょうか?
>>215さんが出した例のような場合、ユーザーはreserveを使います。
どうでしょう? だめ?

244:デフォルトの名無しさん
08/03/14 01:08:07
allocatorを指定するとか。

245:デフォルトの名無しさん
08/03/14 01:26:34
>>243
そう、毎度コピーするのは無駄と誰もが思ったから、
今度の規格改定でムーブセマンティクスというものが導入されようとしている。

246:オガちゃん萌え ◆tyvkWCNtzY
08/03/14 01:27:09
インフラはmemsetやらをやたら使うよ
アーキテクチャ依存すんだからOOPは役に立たん
ドメインでアーキテクチャ依存せんようにするにはやむえない
…が、インフラのC型記述は拡張子.cにして欲しい
イヴァーヤコブソンはそんなユースケース駆動モデルを奨めている
STLですらQACでNGになられたんじゃ参るストーン

247:デフォルトの名無しさん
08/03/14 01:47:52
>>245
彼が不満に思っている状況の大半では,
move semantics は何の改善ももたらさないのでは?

248:デフォルトの名無しさん
08/03/14 01:53:02
そうか?移動なら、コピーに比べ格段に低コストだし、
前のオブジェクトのデストラクタは実質やることなくなる。
こういう問題だと思っていた。214が納得するかどうかは別としてだけど。

249:デフォルトの名無しさん
08/03/14 02:09:19
>>248
memcpy によってコピーできるオブジェクトというのは,
(C++0x において条件が緩和される) POD 型のオブジェクトに
およそ相当すると思いますけれど,これらのオブジェクトに対しては
コピーの操作と (move semantics でいうところの) move の操作は
同じ操作になると考えられるので「move semantics によって改善される」というのは
まずいのではないかな,と.

デストラクタに関しても, move を使っても copy を使っても
「実質やることがない」のはなんら変わりはないと思います.

250:デフォルトの名無しさん
08/03/14 10:11:23
>>249
ああ、たしかにPODだとそうだね。

言葉足らずですまん。俺は非POD型を入れることことを考えていた。
というのも243でデストラクタを呼び出さなければならないと言っているから、
214=243は非POD型を念頭に置いているのだと思ったため。

251:デフォルトの名無しさん
08/03/14 12:04:02
>>243
手元のVC8ではvector<char>とかvector<int>ならmemmoveを使ってくれたよ。
アラインメントを考慮してrep movsdで転送。

struct Foo{int a; int b;}; vector<Foo>だと単純にループ1まわりにつき
8byte転送するようなコードになってた。

PODを判定できれば両方memmoveに出来るんじゃないかな。


252:デフォルトの名無しさん
08/03/14 12:23:37
わかってない子が来た

253:251
08/03/14 13:03:30
ん、俺のこと?
俺はただ、>>243がpush_backでのバッファ拡張時にmemcpyやmemmoveのような
効率的なコピーが使われないと思いこんでいるようだったから、わかりやすい
反例を示しただけだよ。

>>243
> *ほとんどの* ケースでは、単純なmemcpyで済みそうなのに、

それで済むケースは実際にそうなる場合があるよ、と。


254:デフォルトの名無しさん
08/03/14 13:22:12
>>232のアホ顔軍曹に習ってくる様にw


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

4969日前に更新/192 KB
担当:undef