C++相談室 part32

このエントリーをはてなブックマークに追加
871デフォルトの名無しさん:04/07/16 13:39
#include <stdio.h>

int a;

int main()
{
char str[128];

for(a=0;a<128;a++){


printf("文字列を入力してください(127文字以内)\n");
scanf("%s",str);
if(str[a]==NULL)
{
break;
}
str[a] = str[a]+1 ;
printf("\t%s!\n" , str);

}

return 0;

}
>>871
#include <stdio.h>
int main()
{
 char str[128];
 printf("文字列を入力してください(127文字以内)\n");
 scanf("%127s",str);
 for(int i = 0; i < 127; i++)
  if(str[i] == '\0')
   break;
  else
   str[i]++;
 printf("\t%s!\n" , str);
 return 0;
}
std::basic_stringのことなんですが
VC6に付いてる<string>を見ると

std::string a("abc"), b;
b = a;

とすると、aとbが保持する文字列の実体は同一で、参照カウンタで文字列の実体の寿命を管理してました。
参照カウンタはクリティカルセクション等で保護されてないようなので
a, bを別々のスレッドで同時に操作すると危険ですよね?
また、

std::string a("abc"), b;
b = a.c_str();

とすると、a, bが保持する文字列実体は別々になるようです。

こういう振る舞いを定義してる規格とかあるのでしょうか?

スレッドに渡す文字列を上の b = a; のように渡すと危ないですよね。
かといって b = a.c_str(); として、別の実体が作られることを期待していいものかどうか…

ttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcstdlib/html/vclrfthreadsafetyinstandardclibrary.asp
>For writes to different objects of the same class, the object is thread safe for writing:
>・From one thread when no readers on other threads.
>・From many threads.

これには安全だと書いてありますが、上の b = a; では当てはまらないのではないでしょうか?
876873:04/07/16 15:55
>>874-875
まさにこれですね。
いずれ.NETを買うつもりですがとりあえず
前から入れようと思ってたSTLPortを入れてみます。
ありがとうございました。
C++ では stdio をやめて、sprintf とかでも ostringstream にした方がいいですか?
Effective C++ では stdio とは決別すべきと書いてあったのですが、イマイチ踏み切れません…
ostringstreamがそんなに嫌いならboost::formatを使え。
sprintfがどうしても使いたいならsnprintfを使え。
あ、嫌いじゃないですよ。全然。
ただ MS とかのコード見ててもあまり登場しないもんだから
なんか問題があるんじゃないかと思ってたわけです。。
printf 系の場合、

string s = "aaaaa";
printf( "%d", s );

とかやってもコンパイルエラーにならない。
その点、basic_ostream 系ならば、そのあたり適切に判定してくれるし、
自分で型定義もできて便利。
>>832
ランダムイテレータ の場合、ita と itb をランダムイテレータだとすると、

ita == itb; が true の場合、
*ita == *itb; が true を返すことは企画上保障されているが、
&*ita == &*itb; にかんしては規程されていない。

たとえば、UTF-8 文字列に対応した、UTF-8 Iterator itu があったとして、
*itu が UCS-4 のコードポイントを int で返したとしてもそれは問題ない。
882881:04/07/16 20:15
でも、>>832 は、std::string についていっているわけだから、
最後の2行は余計か。スマンな
おまいら、printf が好きですね
今のところprintfが最強だからね。
printzが最強
>>869
template<float &f> に汁
887デフォルトの名無しさん:04/07/17 00:45
「クラスAとクラスBの関連」をC++で実装する場合
これで良いのでしょうか?

class B;

class A{
    B* related_b_ptr;
public:
    A( B* b_ptr ){ related_b_ptr = b_ptr; }
};

class B{
    A* related_a_ptr;
public:
    B( A* a_ptr ){ related_a_ptr = a_ptr; }
};

関連全てにこんな事やるのは面倒ですし、感覚として間違っている
気がするのですが、代替手段が分からないんです。

例えば引数でその都度、関連クラスを渡したりすのは、第3のオブジェクトが
無理矢理必要なこともあって、全然オブジェクト指向じゃなくなる気がします。

関連って実際はどんな事なんでしょうか。
>>887
class A のインスタンスをどうやって作るんだ?
889デフォルトの名無しさん:04/07/17 00:50
>>887
friendクラスとか、入れ子クラスは?
890デフォルトの名無しさん:04/07/17 00:52
>>887
(889の続き)
どーせ、モロ依存しまくりなら
変に分離して書こうとすること自体間違ってる
>>887
クロコクラスとか、グレコクラスとか
>>887
UMLでいうところのnavigabilityが双方向ならそれでいいんじゃないですか?
「感覚として間違っている」のは、
実装方法ではなくnavigabilityが双方向であることだと思います。
循環依存ですから(それが必要なことももちろんある)

navigabilityが片方向なら、メンバとして持つなり
1対多ならコレクションでもつなりの実装方法があります。

生成は、包含なら包含元クラスで行いますし、
そうでない関連ならどこかに生成元がいるはずです。
894887:04/07/17 10:30
すいません、すぐレス頂けるとは思わず。
皆さんレスありがとうございました。

>>888-891
インスタンスはポインタを介してなどでしょうか。
疑問に思っていた関連とは、どこにでもあるありふれた関連の事だったんです。
なのでfriendや入れ子は更に大げさかなと。

>>892
おかげで良く分かりました。言われてみれば関連といえど、その実態はほとんど全てが
片方向でした。難しいだけと思っていた専門用語が、ここまで便利とは…。

生成について、しばしばパターンなどと一項目あげて大げさに
取り上げられている理由も、合わせて理解できた気がします。
char_traitsを見てて疑問に思ったのですが
char(0), char() と '\0'、wchar_t(0), wchar_t() と L'\0' は
等しくなることが保証されているんでしょうか?
#include <iostream>

class A {
public:
  static int main() {
    std::cout << "main" << std::endl;
    return 0;
  }
};

int main = A::main();

何気なく書いてみたのですが、これが動いてしまう理由がわからないです。
int main = A::main(); と書いてるのにコンパイルできてしまうってことは、
mainはデフォルトで関数ポインタとして扱われるということでしょうか?
>>896
初期化付きのグローバル変数なだけだろ。
>896
これだとメイン2回実行されるの?
手元に今コンパイラないのでわかんね
>int main
ってかいといて何言ってんだよw
>>896
コンパイルはできるのはわかるけど動く?
mainが未解決とでるんだけど。
>>896
リンカーはmainへ実行を移すコードcrt.oとリンクするけどmainの中は0が入ってる
その後ろに何があるかは環境による。
C++の処理系はmainと言うグローバル変数の初期化をcrt.oがmainを呼ぶ前に実行する
これがA::main()を実行しているのでメッセージは出力される。
vector< char > v( istream_iterator< char >( cin ), istream_iterator< char >() );
が関数宣言になる使用を思い出したのは漏れだけではないはず
何故コンパイルエラーになるか分かりません。

#include <iostream>
#include <algorithm>

struct A {
int x;
int y;
bool operator<(struct A a) {
if(this->x != a.x)
return this->x < a.x;
else
return this->y < a.y;
}
};

int main()
{
const int size = 100;
struct A a[size];
sort(&a[0], &a[size]);
return 0;
}
エラーメッセージ

/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h: In function `const struct A & __median<A>(const A &, const A &, const A &)':
/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h:1283: instantiated from `__introsort_loop<A *, A, int>(A *, A *, A *, int)'
/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h:1320: instantiated from here
/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h:46: passing `const A' as `this' argument of `bool A::operator <(A)' discards qualifiers
/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h:47: passing `const A' as `this' argument of `bool A::operator <(A)' discards qualifiers
/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h:49: passing `const A' as `this' argument of `bool A::operator <(A)' discards qualifiers
/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h:53: passing `const A' as `this' argument of `bool A::operator <(A)' discards qualifiers
/usr/lib/gcc-lib/i386-redhat-linux/2.95.3/../../../../include/g++-3/stl_algo.h:55: passing `const A' as `this' argument of `bool A::operator <(A)' discards qualifiers
905896:04/07/17 15:13
レスどうもでした

>>898
1回だけ"main"と表示して終了するだけです。

>>900
bccでコンパイルして実行確認しました。

>>901
解かりやすい説明ありがとうございました。
プログラムの実行の仕組みとかも調べると、より理解も深まって面白そうですね。

>>902
使い方など、ぱっと見何だかわからないです。
勉強が必要ですね。
>>903
- bool operator<(struct A a) {
+ bool operator<(const struct A &a) const{
907896:04/07/17 15:33
恩返しにと>>903にレスしようと思ったら、既にされてましたね。
g++ではなくbccのコンパイラだと>>903みたいのでもコンパイルできてしまったりして、
環境による大きく依存があるのだなぁと感じました。

そこで、さきほどの>>896のプログラムも少し試してみました。
bccでコンパイルしてWindows上で実行すると気づかなかったのですが、
g++でコンパイルしてLinux上で実行すると、"main"を表示したあと、
Segmentation faultで落ちてました。
これは>>901を参考に解釈すると、A::main()が実行されたあとに、
mainの後ろの不定な領域を実行しようとして落ちたという認識で良いのでしょうか?
>>895 OK
>>906
>sort(&a[0], &a[size]);
std::sort(&a[0], &a[size]);
>>907
> mainの後ろの不定な領域を実行しようとして落ちたという認識で良いのでしょうか?
正解。
911906:04/07/17 16:17
>>909
2.95.3
912デフォルトの名無しさん:04/07/18 00:09
CHoge a,b,c;

c = a + b;
をできるように

CHoge& CHoge::operator+(CHoge& hoge)
{
CHoge tmp;
tmp.value = (*this).value + hoge.value;
return tmp;
}

なんてoperatorを書いたのですが、一時オブジェクトの参照を
返してもいいんですかね?
913デフォルトの名無しさん:04/07/18 00:17
this->valueとかけよ。
>912
CHoge のデストラクタで value = 0 と代入してみ
>>912
自分で参照とか言ってるのに何言ってんの?
916912:04/07/18 00:45
解決しました
一番最悪なパターンですね
なんか発情してきました
どうすればいいですか?
919918:04/07/18 03:33
解決しました
早漏ですね