1 :
デフォルトの名無しさん :
2009/02/12(木) 15:34:43
STLつかうと一気に実行ファイルサイズが10倍に?! 環境によるだろ。 俺はBorland-C++5.6.2に -D_RTLDLL オプションを指定して、極力 ランタイムを使用するようにして使っているが、例えばstd::vectorを 使っても使わない時と比べ10Kほどしか増えない すげえ。ダイナミックリンクしといてファイルサイズが増えないとかいってるよ。この人。 C1010: プリコンパイル済みヘッダーの検索中に予期しない EOF を検出しました。 とかいうエラーが出るんだけどこれってどうすればいいの? #include <stdafx.h> 後死ね。 言葉が悪いな。それで教えているつもりか。 まぁヒントぐらいにはなったな。 うむごくろう。
真スレです 仲良く使ってね楽しく使え クズども
基本的なことなのですが、質問させてください。 DLL のクラスの変数をほかのアプリケーションから利用したいのですが、アプリケーションのビルドでリンカーエラーになってしまいます。 ---DLL のクラスのヘッダーの一部--- class __declspec(dllexport) Sample1 { public: Sample1(void); ~Sample1(void); public: static const char *str_data; }; ---DLLのクラスのCPPの一部--- const char *Sample1::str_data = "Hoge"; ---アプリケーションのCPPの一部--- _TCHAR buf[255]; _swprintf(buf, _T("str_data = %s\r\n"), Sample1::str_data); ::OutputDebugString(buf); DLLはビルドできますが、アプリケーションでは error LNK2001: 外部シンボル ""public: static char const * const Sample1::str_data" (?str_data@Sample1@@2PBDB)" は未解決です。 とでてしまいます。 よろしくお願いします。
DLLを使う側では、__declspec(dllimport)付きでクラス定義している?
6 :
4 :2009/02/13(金) 00:24:20
>>5 していません。 __declspec(dllexport) はしているのですが。
dllimport については使ったことがなかったので調べて見ます。ありがとうございます。
7 :
4 :2009/02/13(金) 00:54:46
すいません。まだ、少ししか dllimport について調べていないのですが、もう一度質問させてください。
以下のように アプリケーションのヘッダーに dllimport を追加しましたが、同じリンカーエラーになりました。
---アプリケーションのヘッダー---
#include "resource.h"
#include "..\\Test_class\\Sample1.h"
#pragma comment(lib, "Test_class.lib")
__declspec(dllimport) Sample1;
リンカーエラー
Test_classApp.obj : error LNK2001: 外部シンボル ""public: static char const * const Sample1::str_data" (?str_data@Sample1@@2PBDB)" は未解決です。
ちなみに、VC++ 2008 Express を使っています。
static const のメンバ変数の書き方は、
ttp://frog.raindrop.jp/knowledge/archives/000281.html などを参考にさせていただいたのですが、問題ないように思えます。
はっきりいって、原因がさっぱりわかりません。
強いていえば、やはり dllimport のような DLL をつかった場合の設定を間違えているのかと思っています。
今日はもうレスができないかもしれませんが、よろしくおねがいします。
関数のときと同じで、DLLを作る側はclass __declspec(dllexport) Sample1にして、 使う側はclass __declspec(dllimport) Sample1になるようにしないとだめだよ。
10 :
デフォルトの名無しさん :2009/02/13(金) 08:49:08
オブジェクトを作成するとき クラス名 ob1; クラス名 *ob2; この上と下の違いはなんでしょうか? 上は新しくクラスをつくっていて 下はクラスのアドレスを渡しているということですか?
>>11 上はオブジェクトの作成。
下はオブジェクトへのポインタの作成。
ただの宣言文なのでアドレスを渡しているわけではない。
14 :
デフォルトの名無しさん :2009/02/13(金) 18:51:59
15 :
デフォルトの名無しさん :2009/02/13(金) 22:35:57
こっちが先だな
16 :
デフォルトの名無しさん :2009/02/14(土) 15:16:58
age
17 :
赤西仁 :2009/02/14(土) 16:31:29
2年間悩んでます。お力をお貸しください。
PSのアークザラッドUというタイトルのゲームの、ゲーム画像(歩行画像など)を抽出したいのですが、
かれこれ1年ほど経ちますが、なかなかうまくいきません。
*もちろん抽出した画像は個人範囲内で利用するつもりです。
◆試してダメだったこと
ネット上からダウンロードできる、ありとあらゆる抽出系ツールを試した。
(ちなみに他のゲームはほとんど抽出可能)
◆教わったこと
・アークザラッドUは独自の画像形式を使っているから抽出できない。
・PS上で表示されてるということは絶対に摘出はできるはず。
・
ttp://www.gradius2.com/index.php?UID=1174775153 ◆抽出は不可能ではないということを知ったとき
2ちゃんねるで質問したところ、
ある方が実際にキャラクターの歩行画像を抽出して
私が立てたスレにアップしてくださいました。
スクリーンショットじゃダメなんです。どうか皆さん、お力をお貸しください。お礼は絶対にします。
コピペ君って本当馬鹿だな、まで読んだ。
19 :
赤西仁 :2009/02/14(土) 16:35:37
20年間悩んでます。お力をお貸しください。
PSのアークザラッドUというタイトルのゲームの、ゲーム画像(歩行画像など)を抽出したいのですが、
かれこれ1年ほど経ちますが、なかなかうまくいきません。
*もちろん抽出した画像は個人範囲内で利用するつもりです。
◆試してダメだったこと
ネット上からダウンロードできる、ありとあらゆる抽出系ツールを試した。
(ちなみに他のゲームはほとんど抽出可能)
◆教わったこと
・アークザラッドUは独自の画像形式を使っているから抽出できない。
・PS上で表示されてるということは絶対に摘出はできるはず。
・
ttp://www.gradius2.com/index.php?UID=1174775153 ◆抽出は不可能ではないということを知ったとき
2ちゃんねるで質問したところ、
ある方が実際にキャラクターの歩行画像を抽出して
私が立てたスレにアップしてくださいました。
スクリーンショットじゃダメなんです。どうか皆さん、お力をお貸しください。お礼は絶対にします。
PS1エミュがあるんだから吸い出せば速攻できるのになw
65536年間悩んでます。お力をお貸しください。
PSのアークザラッドUというタイトルのゲームの、ゲーム画像(歩行画像など)を抽出したいのですが、
かれこれ1年ほど経ちますが、なかなかうまくいきません。
*もちろん抽出した画像は個人範囲内で利用するつもりです。
◆試してダメだったこと
ネット上からダウンロードできる、ありとあらゆる抽出系ツールを試した。
(ちなみに他のゲームはほとんど抽出可能)
◆教わったこと
・アークザラッドUは独自の画像形式を使っているから抽出できない。
・PS上で表示されてるということは絶対に摘出はできるはず。
・
ttp://www.gradius2.com/index.php?UID=1174775153 ◆抽出は不可能ではないということを知ったとき
2ちゃんねるで質問したところ、
ある方が実際にキャラクターの歩行画像を抽出して
私が立てたスレにアップしてくださいました。
スクリーンショットじゃダメなんです。どうか皆さん、お力をお貸しください。お礼は絶対にします。
ヘッダで using namespace はご法度な話で、 // hoge.hpp #include <色々> namespace hogeImpl { using namespace 色々; class hogeClass { ... } } } using hogeImpl::hogeClass; こんな感じで押し込むのはダメ?
23 :
赤西仁 :2009/02/14(土) 21:10:56
00000010年間悩んでます。お力をお貸しください。
PSのアークザラッドUというタイトルのゲームの、ゲーム画像(歩行画像など)を抽出したいのですが、
かれこれ1年ほど経ちますが、なかなかうまくいきません。
*もちろん抽出した画像は個人範囲内で利用するつもりです。
◆試してダメだったこと
ネット上からダウンロードできる、ありとあらゆる抽出系ツールを試した。
(ちなみに他のゲームはほとんど抽出可能)
◆教わったこと
・アークザラッドUは独自の画像形式を使っているから抽出できない。
・PS上で表示されてるということは絶対に摘出はできるはず。
・
ttp://www.gradius2.com/index.php?UID=1174775153 ◆抽出は不可能ではないということを知ったとき
2ちゃんねるで質問したところ、
ある方が実際にキャラクターの歩行画像を抽出して
私が立てたスレにアップしてくださいました。
スクリーンショットじゃダメなんです。どうか皆さん、お力をお貸しください。お礼は絶対にします。
>22 外部から hogeImpl::XXX として「色々」の中のものがアクセスできる、つまり「色々」の中のものは hogeImpl の要素なんだ、と思えるのならば OK。 それでも大抵は using namespace よりは using 宣言になるだろうけど。
>>24 説明が足りなかった。ごめん。ヘッダ利用者は hogeImpl 以下を使わない。
namespace hogeImpl {} をプライベートな名前空間だと思って
好き勝手に実装を書き、外に見せたいものだけ using hogeImpl::... しておく。
そうすれば、実装部分で using namespace std; していても、
余分な名前が漏れることは防げると思うんだけど、そういうコードを見たことがないので
何か落とし穴があるのかと不安で。
>25 > namespace hogeImpl {} をプライベートな名前空間だと思って > 好き勝手に実装を書き、外に見せたいものだけ using hogeImpl::... しておく。 これ自体は boost とかでも頻出パターン(大抵は detail という名前空間)。 using directive の使用についてはライブラリ利用者としては問題ないだろうけど、 実装者側で名前の衝突が発生する危険はある。 boost だと(意図的に名前を持ち込む場合以外の) using directive は関数ブロック内に 限定した利用がほとんどのようだ。 できるだけ影響範囲を限定しよう、という意図だと思う。
>>26 なるほど。ありがとう。
やはり using は、関数ブロック内程度に留めておくことにします。
STLスレから誘導されてきました。 質問があります。 STLはヘッダにその実装が書いてあるわけですが、 ということは「翻訳単位毎にコードが生成される」のでしょうか? a,cpp b.cpp 両方<vector>をincludeし、両方で vector<int> が使われていた場合、vector<int>のコードは2つ作られてしまうのでしょうか? EXEファイルの容量がガンガン増えるような気がするのですが・・・
そう。ガンガン増える かしこいコンパイラなら少しは最適化してくれるけど当てにしちゃいけない
普通はリンク時に1つにまとめられるか、インライン展開して消え去るかのどちらかだと思う。 さすがに同じものが2つも残るのは珍しいだろう。
C++の規格では1つにまとめるよう要求しているぞ。 1つにまとめなかったらstaticメンバ変数とかどうなるんだよ。
>28 真・スレッドリスターター(以下略)をあぼんしてたので誘導されてるのに気づかず向こうで答えちゃった。
a.cppでインクルードしたテンプレートから作ったvector<int>と b.cppでインクルードしたテンプレートから作ったvector<int>が 同じである保証はどこにもないんだから、まとめようがないだろ 普通に考えれば オレオレ<vector>が使われてないという前提なら<vector>は全部一緒だから 標準ライブラリだけ特別扱いしてでまとめてくれるとか、そういう話?
まとめようがなかったら 一体この A<int>::a はどうなるんだよ。 翻訳単位事に作られたら規格違反じゃねぇか。 template <typename T> struct A { static T a; }; template <typename T> T A<T>::a;
別の所にこれがあったらどうするんだよ 勝手にまとめられるわけないだろ template <typename T> struct A { static int a(T); };
>>33 単一定義規則 (ODR) と言って、その保証をするのはプログラマの仕事。
なんだ。池沼か。日本語通じねえ。
ダメだこりゃ
>>35 同名の複数の実体をまとめるかまとめないかはコンパイラ・リンカしだい。
>>36 が言うように
いずれにせよプログラマが同一であることを保障する必要がある。
ごめん、よくわかんないんだけど、
>>28 さんが実際にいくつもa.cppやb.cppらを作って全部リンクしてみて実際に実行ファイルの容量がでかくなるか試してみればいいんじゃないの?
44 :
デフォルトの名無しさん :2009/02/17(火) 23:47:42
あ
>>42 ボケナスとはずいぶん古風な煽り方をなさるw
どこが古風だスットコドッコイ
47 :
デフォルトの名無しさん :2009/02/18(水) 18:27:43
寿司喰い姉ぇでしめくくるんだよな
当たり前田のクラッカーだ。
何言ってんだい、このでこシャッポ。
標準C++ライブラリの範囲で std::stringとstd::wstringの変換って出来ません? std::ostringstreamとかを使うのも可で、とにかく標準C++の範囲で。
>>50 std::codecvtを使うらしいが詳細はシラネ
53 :
50 :2009/02/19(木) 13:58:44
ありがとう。 今から見てみるわ。
コードの変換っつて難しいね 標準だけとコンパイラによって微妙に違ったり OSに渡すのに適してなかったり。
std::mbstowcs と std::wcstombs じゃだめ?
リンク時に「未解決のシンボル"public:_thiscall CDunBase::CDunBase(void)"が関数"public:_thiscall CDun01::CDun01(void)"で参照されました。」 というエラーが出るのですが、原因が分かりません。
CDunBase::CDunBase(void) の定義が無いと言ってる
>>56 たとえば CDun01 の継承元 CDunBase の引数を持たないコンストラクタが
宣言されているが定義されていない場合、そんなエラーが起こるでしょう。
CDunBaseのディフォルトコンストラクタがないんじゃないかな。
うぁはは、被り捲くり。
なるほど、コンストラクタが定義されていなかったのですね。 やっぱり理解してないものはあまり使うべきじゃありませんね。
62 :
50 :2009/02/20(金) 06:48:28
>>55 std::wcstombsとかでも出来るのか。
なんかこういうのホント分からん。こんな関数みたことねぇ。
>>62 >>52 のコードを書いた張本人だけど、ぶっちゃけ俺もロケールの動作とか関数とかはよく判っていない。
そもそもwchar_t関係は具体的な定義が仕様になかったり、VCとgccでwchar_tの大きさが違ったり、
さらにVCの各Ver.ごとに致命的なバグとか仕様の違いとかが結構あったりして、
正直C++標準のロケールは使い辛いと言わざるを得ない。
あまり本格的でない用途に使うならwchar_t/codecvtでもいいと思うけど、
ちゃんとしたいならやっぱりICUとかの外部ライブラリを使って、
さらにプリプロセッサでwin32と*nixを分岐させるとかの面倒なことをしなきゃだめだと思う。
//
>>52 の引数2つの関数は、たぶん予めstd::locale::global(std::locale("japanese"));しないといけなかったはず。
>>63 そうなんですか。wchat_tはこのままだとC++の黒歴史状態に?
そして、まさかあのコードを書いた方がここにいらっしゃるとは、2chって(てかネットって)わからない。
あのぅ、俺は hoge(int &arg) を参照渡しだと思っているんだが、 hoge(int *arg) int i; hoge(&i) これも参照渡しって言うの? 誰かこのモヤモヤを取ってくだしあうあ
66 :
デフォルトの名無しさん :2009/02/20(金) 23:03:04
厳密にはC++に「参照渡し」は存在しない hoge(int &arg)は参照の値渡しだし hoge(int *arg)はポインタの値渡しだし 渡された値を参照にも使えるというだけ
>>65 まさかとは思うけど、参照とアドレスを取得する時に使う&の区別は付いているよね?
int a=&b;
と
int &x=y;
とでは意味が全く違うことは知ってるよね?
69 :
68 :2009/02/20(金) 23:20:08
あ。 int a=&b; は int* p=&b; の間違いっす!
70 :
デフォルトの名無しさん :2009/02/20(金) 23:34:40
>>67 じゃあ、厳密な「参照渡し」ってなんだよ。
hoge(int &arg)が正真正銘の参照渡しじゃなければ、何が違うというのだ?
あぁ、勘違いしてたわ int a = &b; これも(意味は異なるが)参照だと思ってた ということは参照渡しって hoge(int &arg) だけなんだね sanx
>>67 参照の値渡しwww
hoge(int &arg) は正真正銘参照渡しだ。
参照は再代入できないって点をよーく考えてみるんだな。
>>70 C++の参照はポインタのシンタックスシュガーに過ぎない
裏でやってるのはあくまでアドレスの値渡し
>>72 意味がわからない
じゃあhoge(int *const arg)は「正真正銘参照渡し」だと言いたいの?
なんでもかんでもシンタックスシュガー♪
>>74 ポインタのシンタックスシュガーだと規格に載ってるのか?
>>74 FORTRAN は参照渡しだけど
C から FORTRAN の関数呼ぶときゃ
引数をポインタにして扱うだろw
裏でアドレス渡していようが、それが見えなきゃ参照渡しだ。
あと、再代入ができない、というのは、お前に対してははしょりすぎたな。
参照そのものを触ることができない、というのが一番重要な点だ。
常に参照先ののものにしか触る事が出来ない。
ポインタは参照元に触る事が出来る。
const だろうがポインタのアドレスをとることもできる。
参照だのreferenceだのという名前が付いてるからって、その通りの実体だと思うと足元すくわれるよ 特にC++という言語はそうだ int&というものはint*と基本的には一緒 書き方とできる操作の範囲がちょっと違うだけ
>>77 FORTRANの下りは当たり前じゃん
Cから呼ぶんだからCの作法で呼ぶ
それは参照に使えるアドレス値の値渡しだ
参照のアドレス値が取れるかどうかなんて大した問題じゃないね
参照はコピーできるんだから、番地は見えなくたってアドレスを扱うことはできてる
FORTRAN の参照だって別の関数に渡しゃコピーできるだろw
>>78 や
>>79 あたりは裏の構造に頭がいきすぎて
参照ってなんなの? ってのが分かってないようだな。
俺なりに整理した。 void f(int *p)は、値渡しの一種であるポインタ渡し void f(int &p)は、参照渡し Cには値渡ししかないがC++には参照渡しもある >参照はコピーできる 参照しているものはコピー出来る 参照している先のアドレスもポインタを使えばコピー出来る けど、参照の参照(参照自体のアドレスの取得)は出来ないよ
「参照渡し」 という概念を、C では アドレスを値渡しすることで実現している、ってことじゃないの 概念的には参照渡しだけど、Cの用語としては参照渡しではない 知らないけど
リロードせずに書き込みましたすみません><
>>82 取ることが言語で禁止されてるだけでアドレスはメモリ上のどっかにあるはずなんだが
なんでアドレス値をプログラムから見ることにこだわるの?
>>86 そんなこといったら参照渡しなんて存在しなくなるぞw
>>84 int n;
f(&n);
n にとっては参照渡しと言えなくもないが、
&n を入れた変数自体も触れるので完全な参照渡しとは言えない。
参照渡しを値渡しを使って無理矢理エミュレートしている、程度の代物。
無条件で「参照渡しだ!」と言っちゃうと色々困った理解をする人が現れるのを
何度も見た事があるので、口が裂けても参照渡しと言いたくはない。
参照のアドレスを見たがってる人は 関数ローカルの参照作ってスタック覗けば多分「参照の値」が見えると思うよ 注意しないと最適化で消されちゃうだろうけど
>>77 C++からならC++参照使ってもできるよ。
そこでは、Fortranの参照とCのポインタとC++の参照の内部表現がたまたま共通だったから。
何々?結局どうなったん? 俺もまぜて
>>91 要するに内部表現は参照渡しかどうかにゃ関係ないっつー話だ。
94 :
92 :2009/02/21(土) 01:10:27
考えてみれば 「ソースコードに記述したとおりに標準C++の規格準拠に動けば 内部でアドレスを使おうが、 あるいはどのような非効率で妙な内部表現であったとしても、 そんなん全然関係ないよ」 ってことか??
結構勉強になったわ 一番違いがわかりやすいのは、参照渡し⇒「仮引数に左辺値」がくる int f(int &p)に対してf(1)って呼び出しは出来ない。1は右辺値だからな
const 参照は右辺値を引数にできる。 しかし、参照するのは右辺値そのものではなく、 それをコピーして作ったテンポラリオブジェクト(左辺値)だけどね。
97 :
92 :2009/02/21(土) 01:13:57
>>95 int f(const int &p)
というコードを書いてみ。
書き込む前にはリロード。 これ常識。
96のプロフェッショナルぶりにワロタw 書いてみるもんだな、勉強になたよ
100 :
92 :2009/02/21(土) 01:16:42
サーセン
この辺、右辺値参照でまたプログラムがだいぶ変わるのかなぁ
変わんないだろう 気を遣って書かない限りすぐ左辺値参照に倒れるようになってるし
クラスを作ったら、「コピーコンストラクタ・コピー代入演算子」を書かねばならない(あるいは禁止にする) の鍵括弧の中にムーブコンストラクタ・ムーブ代入演算子が増えるだけ。 (コピー不可・ムーブ可という選択肢もあるが) あとはvectorの中とか関数戻り値でコンパイラが生成するコードとかで勝手にやってくれる。
ムーブコンストラクタとムーブ代入演算子は必要なければ書かなければいいだけだから あんまり気にしなくていい
しっかし、今でさえC++の本ってごっついのに、 C++0xに対応したらどんなごつさになるんだ?
swapもコンストラクタなみの扱いにしてほしいな std空間に定義していく今のやり方はあまり良くないだろうと
>>106 swapは自分の名前空間で定義するのが主流になりつつあるでしょ。
あとは、標準でいくらかお墨付きになるのを待つだけで。
全部読むだけで人がしぬ(寿命で)ごつさになります。
細心の注意を払わないと上手く最適化されない言語仕様
110 :
デフォルトの名無しさん :2009/02/21(土) 11:05:45
カレントスレッドのスタックサイズを取得したいんだけど、どうすればよい??
環境依存です。はい、次の方どうぞ。
112 :
デフォルトの名無しさん :2009/02/21(土) 11:16:44
>>111 ちょwww待って先生!!重症なんですw
とりあえず Windows で教えてください。
EXEのヘッダにエントリがあった気もするし…
サイズじゃなくても、sp の最小値でもいいです。
取れませんか??
Win32APIスレに行った方がいいぞ
114 :
デフォルトの名無しさん :2009/02/21(土) 11:50:35
>>113 よく考えたらスレチでしたorz
APIスレ行ってきます!
名前空間の命名にあたって何か規約ないし慣習はありますか? 例えば最初が_で始まってはならないなどです
予約語にしてはいけない、以外の慣習は、人それぞれだろう。 まあ、全部大文字はマクロに使う人が多いから使わない方がいいだろう、程度しか。
117 :
115 :2009/02/21(土) 16:57:22
未だにテンプレートを何に使えばいいのか分からないのですが何か良い本はありますか?
>>118 STLとshared_ptrを使ってみるとありがたみがわかる。
>名前空間の命名 全部小文字派とアッパーキャメルケース派に大別されるのではないかな。 クラス名と被らないような、より抽象的なカテゴリ名を使ったり、 一部.netでやってるように複数形にしてお茶を濁したり。
121 :
115 :2009/02/21(土) 17:14:16
>>120 個人的にはCamelCaseよりcamelcase派です。
いずれにせよ、そこまで強いルールはないんですね。
N付ける派もいたか
>>122 どういうことですか?
namespaceのNってことですか?
そのとおり
自分の名前を頭に付けている俺
名前空間名が型名や変数名と混ざることは少ないから 変な細工はあんまりいらないと思う
今度から頭に母ちゃんってつけようぜ
テンプレートの使い方で分からないんだけど、 template <typename T> class Myclass { public: T mem; //他、Tを使ったメンバ関数・メンバ変数が多数 int foo(int x){std::cout << x << std::endl;return x;} double foo(double x){std::cout << x << std::endl;return x;}; unsigned long foo(unsigned long x){std::cout << x << std::endl;return x;}; }; のようなクラスがあって、呼び出すときは Myclass<char> hoge; hoge.foo((int)-1); hoge.foo((double)3.14); hoge.foo((unsigned long)42); のように使っている状況。 で、この3つのfooをテンプレートにしてまとめたいんだけど、どうすりゃいいかね?? template <typename T,typename U> class Myclass {//〜〜}; とは意味合いが違うじゃん。。。
template<typename U> U foo(U x){std::cout << x << std::endl;return x;} をメンバにすればいいだけじゃないの
>>128 できた。
テンプレートの中にテンプレートを入れ子にできるのか。
ありがとう。
131 :
128 :2009/02/21(土) 18:26:11
今度はコンストラクタで死んだ。 template <typename T> class Myclass { public: T mem; //他、Tを使ったメンバ関数・メンバ変数が多数 Myclass(); template<typename T,typename U> Myclass(U x);//コンストラクタ }; template <typename T> Myclass<T>::Myclass(){} template <typename T,typename U> Myclass<T>::Myclass(U x){} こうするとbccにて テンプレート 'Myclass<T>' に対して宣言されたテンプレートパラメータが多すぎる 'Myclass<T>::Myclass(U)' は 'Myclass<T>' のメンバーではない 'Myclass<char>::Myclass(int)' に一致するものが見つからない(関数 main() ) って言われた。 int main() { Myclass<char> hoge; Myclass<char> piyo(42); return 0;} です。 この場合はどうやって宣言したらいいですか??
template<typename U> Myclass(U x);
133 :
128 :2009/02/21(土) 19:44:41
>>132 クラス内の定義はそれでいけた。
クラス外はどうすればいい?
template <typename T,typename U>
Myclass<T>::Myclass(U x){}
だとダメっぽいんだが
template <typename T>
template <typename U>
Myclass<T>::Myclass(U x){}
にしてみたら出来る。
これで、間違ってない?
operator+=を作ってそれを使うのがベストじゃね というかeffective c++位読んだ方が良い
>>133 順番に考えればいい
普通のクラスのコンストラクタテンプレートならこう書くだろう
template <typename U>
NormalClass::NormalClass(U x){}
このNormalClassを具体化に置き換えてみる
template <typename U>
MyClass<int>::MyClass<int>(U x){}
テンプレートの規則からコンストラクタ名の方の<int>は省略できる
template <typename U>
MyClass<int>::MyClass(U x){}
このintをテンプレート化すると
template <typename T> template <typename U>
MyClass<T>::MyClass(U x){}
ほらできた
わー、すごーい。ヤッターー!
138 :
133 :2009/02/21(土) 21:17:33
>>136 ありがとう!!
template <typename T>template <typename U>
Myclass<T>::Myclass(U x){}
なんだけど、これをUの部分だけexplicit instantiationすることは出来る?
(まあまだ完全にインスタンス化されないからexplicit instantiationとは言わないだろうが。)
template <typename T>
class Myclass
{
public:
T mem;
//他、Tを使ったメンバ関数・メンバ変数が多数
Myclass();
template <typename U> Myclass(U x);//コンストラクタ
template <typename U> U bar(U x);//適当な関数
};
この時、一番最後の適当な関数barは
template <typename T>template <typename U>
U Myclass<T>::bar(U x){std::cout << x << std::endl;return x;}
みたいに定義出来ることは
>>136 に今 教わったことで分かるんだが、このU型の部分をdoubleやintなど既にある型でexplicit instantiation(っぽいこと)しておきたい。
現状は、現在はヘッダーファイルと実装のソースファイルを分けている状態で、ソースファイルの末尾で
template class Myclass<char>;
の様にexplicit instantiationしている。
この状態でコンストラクタやメンバ関数bar()をまとめてU型でテンプレートにしようとしたら困っているところ。
>138 explicit instantiation (みたいなことを)したい理由は何? ライブラリを作ってるとかなら explicit instantiation する意味はあるだろうけど、 何がしたいのか良く分からない。 処理系のインスタンス化の実装方法によっては多少コンパイルが効率化されるかもしれないが、 他の処理系ではむしろ効率が悪化したりするんじゃないだろうか。
140 :
138 :2009/02/22(日) 09:26:36
>>139 >>ライブラリを作ってるとかなら explicit instantiation する意味はあるだろうけど、
ライブラリ作ってる。
いろんなところで使っている処理なんだ。。。
そして、ぜーんぶヘッダファイルに実装まで含めてinlineなんてことはしたくない。
カキコテスト
142 :
138 :2009/02/22(日) 10:58:50
Uとしてはint,double,unsigned longを想定する。 この時とりあえずTがcharな場合しか使わないなら、ライブラリのソースファイルで //explicit instantiation<T=char版> template class Myclass<char>; template Myclass<char>::Myclass<int>(int x); template Myclass<char>::Myclass<double>(double x); template Myclass<char>::Myclass<unsigned long>(unsigned long x); template int Myclass<char>::bar<int>(int x); template double Myclass<char>::bar<double>(double x); template unsigned long Myclass<char>::bar<unsigned long>(unsigned long x); とすれば解決することまでは理解できた。
143 :
138 :2009/02/22(日) 10:59:28
だが実際にはTがchar以外の場合もあったら、例えばTがstd::stringやwchar_t,std::wstringな場合に、上のcharの時の物に加えて //explicit instantiation<T=std::string版> template class Myclass<std::string>; template Myclass<std::string>::Myclass<int>(int x); template Myclass<std::string>::Myclass<double>(double x); template Myclass<std::string>::Myclass<unsigned long>(unsigned long x); template int Myclass<std::string>::bar<int>(int x); template double Myclass<std::string>::bar<double>(double x); template unsigned long Myclass<std::string>::bar<unsigned long>(unsigned long x); のように書かねばならないのだろうか? そうだとすると、メンバ関数のexplicit instantiationだけで12行書くことになるよね? (Tで4通り、Uで3通りのかけ算として。) 俺としてはTだけはおいといてU(メンバ関数テンプレート)だけでとりあえず3通りのexplicit instantiation(もどき)なことをしておいて、その後Tを4通りexplicit instantiationできればいいなぁと思っているのだが…。 たいていこういう場合ってC++だとちゃんと逃げ道あるよね?
関数多重定義では駄目なの?
145 :
138 :2009/02/22(日) 14:05:35
>>144 現在がその状況です。
ライブラリのヘッダーファイルが
template <typename T>
class Myclass
{
public:
T mem;
//他、Tを使ったメンバ関数・メンバ変数が多数
Myclass();
Myclass(int x);//int
int bar(int x);//int
Myclass(double x);//double
double bar(double x);//double
Myclass(unsigned long x);//unsigned long
unsigned long bar(unsigned long x);//unsigned long
};
でライブラリのソースファイルの末尾で
//explicit instantiation
template class Myclass<char>;
template class Myclass<std::string>;
template class Myclass<wchar_t>;
template class Myclass<std::wstring>;
としている。
まあ現状問題無く動くいてるんだが、なんかこれって美しくないコードじゃない?
やっぱもう一つテンプレート(Uの部分)にしたくない?
int, double, unsigned long ... でやる事は同じだけど これら以外の型では呼んで欲しくないという事なのかな
147 :
138 :2009/02/22(日) 15:16:19
148 :
138 :2009/02/22(日) 15:21:27
あとまあ Uのところをint, double, unsigned longで明示的にインスタンス化してやらないと ヘッダファイルをインクルードしてソースファイルをリンクしたところで リンカが「みつかりませんよ」エラーを出すと思ったんだが。 class Myclass を template <typename T> class Myclass にしたときそうだった。
引数の暗黙の型変換も許さないなら関数テンプレートでいいと思う。 関数多重定義だと(リンク時でなく)コンパイル時に合致する関数が あるか分かる利点があるけど。
>>149 なるほど。ありがとう。
実は今、別のところで引っかかってる。(さっきのやつと関連しているのだが。)
class Sample_Class
{
public:
Sample_Class();//これは普通の。
template <typename intT> Sample_Class(intT n);
template <typename floatT> Sample_Class(floatT x);
};
Sample_Class::Sample_Class(){}//これは普通の。
template <typename intT>
Sample_Class::Sample_Class(intT n){if(n){std::cout << n << std::endl;}}
template <typename floatT>
Sample_Class::Sample_Class(floatT x){if(x){std::cout << x << std::endl;}};
このようにすると、
エラー E2238 Sample_Class.cpp 14: 'Sample_Class::Sample_Class(intT)' の宣言が複数見つかった
エラー E2344 Sample_Class.cpp 13: 一つ前の 'Sample_Class::Sample_Class(intT)' の定義位置
エラー E2171 Sample_Class.cpp 20: 関数 'Sample_Class::Sample_Class(intT)' の本体はすでに定義されている
と言われてしまう。
まあ当然と言われれば当然なのかもしれないが、
「整数型と浮動小数点型とで処理が別」だけど「整数型はshort,int,long,unsigned〜で処理が共通」で「浮動小数点型はfloat,double,long doubleで処理が共通」
って状況はテンプレートでどうにかならない?
151 :
150 :2009/02/22(日) 17:02:28
テンプレートを使わないならば class Sample_Class { public: Sample_Class();//これは普通の。 Sample_Class(short v); Sample_Class(int v); Sample_Class(long v); Sample_Class(float v); Sample_Class(double v); Sample_Class(long double v); }; Sample_Class::Sample_Class(){}//これは普通の。 Sample_Class::Sample_Class(short v){if(v){std::cout << "整数" << v << std::endl;}} Sample_Class::Sample_Class(int v){if(v){std::cout << "整数" << v << std::endl;}} Sample_Class::Sample_Class(long v){if(v){std::cout << "整数" << v << std::endl;}} Sample_Class::Sample_Class(float v){if(v){std::cout << "小数" << v << std::endl;}} Sample_Class::Sample_Class(double v){if(v){std::cout << "小数" << v << std::endl;}} Sample_Class::Sample_Class(long double v){if(v){std::cout << "小数" << v << std::endl;}} としておけば、 Sample_Class hoge=42; Sample_Class piyo=3.14; と呼び出してもちゃんと該当する物が呼び出されるじゃん。 これをテンプレートにしようとするととたんにつまずいてしまう。
特殊化では駄目なの?
153 :
150 :2009/02/22(日) 18:17:45
>>152 特殊化だと、結局
hort,int,long,float,double,long double
の全てに関して特殊化を定義しないとだめだよね?
それだったら最初から最初からテンプレートを使わない方が良いと思っている。
俺の希望としては
「整数型と浮動小数点型とで処理が別」だけど「整数型はshort,int,long,unsigned〜で処理が共通」で「浮動小数点型はfloat,double,long doubleで処理が共通」
がテンプレートで実現できれば、実装は(整数型と浮動小数点型の)2カ所で済むじゃん。
という発想なんだよねぇ。
C++のテンプレートでは無理なのだろうか。。。
boost の enable_if がそううことするためのものじゃないっけ?
155 :
150 :2009/02/22(日) 18:45:02
>>154 enable_if: 関数テンプレートオーバロードの選択的インクルード. Jaakko Jarvi, Jeremiah Willcock, and Andrew Lumsdaine. これはSFINAE(substitution-failure-is-not-an-error:置換失敗はエラーではない)原理を利用した新しい重要な技術である.
これか。
boostは好きだが、現在取り組んでいる対象はいわば自作のライブラリなのでboostが無いと使えないライブラリにするわけには行かないんだよねぇ。。。
とりあえず
本の虫: Boostのenable_ifについて
http://cpplover.blogspot.com/2008/01/boostenableif.html こことか読んでる。
もしenable_ifの技術を流用して「boostのenable_ifライブラリのインクルードなし」で出来るようだったらこれで解決しそうだが、
まあわざわざライブラリになっているくらいだからたぶん相当めんどくさい事になるのかなぁ。
enable_ifの実装は比較的簡単。
よく使われるからライブラリになってるだけ。
boostのやつをぱくって自分用enable_ifを作ればいいじゃん。
>>151 ならこんな感じでいけるっぽい:
class Hoge {
public:
template<typename U>
Hoge(U v, typename boost::enable_if< boost::is_integral<U> >::type* = 0);
template<typename U>
Hoge(U v, typename boost::enable_if< boost::is_floating_point<U> >::type* = 0);
};
template<typename U>
Hoge::Hoge(U v, typename boost::enable_if< boost::is_integral<U> >::type*) {
std::cout << "整数" << std::endl;
}
template<typename U>
Hoge::Hoge(U v, typename boost::enable_if< boost::is_floating_point<U> >::type*) {
std::cout << "小数" << std::endl;
}
template Hoge::Hoge(int, void*);
template Hoge::Hoge(long, void*);
template Hoge::Hoge(double, void*);
ちなみにis_integralやis_floating_pointは
template<typename> struct is_integral { static const bool value = false; };
template<> struct is_integral<int> { static const bool value = true; };
template<> struct is_integral<long> { static const bool value = true; };
みたいな感じで。
>>156 サンクス
ちょっと出先なので
家に帰ったら熟読させてください。
前スレでfinallyについて質問した者ですが、遅ればせながらBoost.ScopeExitと いうものを発見しました。まさに我が意を得たり。 > Nowadays, every C++ developer is familiar with RAII technique. > It binds resource acquisition and release to initialization and destruction > of a variable that holds the resource. But there are times when writing a > special class for such variable is not worth the effort. > This is when ScopeExit macro comes into play. やはり必要だと思ってる人はいたんだと安心すると同時に、現行C++の範囲でも ここまでできることに少し感動です。 自分で変なテクニックを使うのは気が進まなくても、boostが正式採用するのなら 使ってみようかという気にもなりますよね。
constは非常に良く使う。特に参照と組み合わせて。 しかし、俺はvolatileは使ったことないんだよねぇ。 みんな使うものなん?
ベンチマーク用に最適化を抑制したいときくらいかな。 マルチスレッドなどで簡易的に使う場合もたまにあるけど。
ポインタの指す先がI/Oポートでもない限り volatile なんか出番なし。
いやさ、俺はC++ってよく知らない機能は使わないですごしちゃうんだよね。 だからvolatileを俺が使わないのは俺の知識不足なのか、それともみんなvolatileの出番はそんなにないものなのかが聞きたかったのだ。
普段は無くても困らないが、必要なときには必須 volatile int *n = HARDWARE_DEVICE_ADDR; *n = 1; *n = 1; // 確かに2回代入 こういうのを最適化されないためにはvolatileが要る
intとかに使うことはあるけど、クラスに使うことはないな。
166 :
163 :2009/02/25(水) 18:38:09
volatileが付いていると、constの有無と同じでなんか変にコンパイルエラーになるんだが。 signatureが違うからオーバーロードの時に困っているだけだが、いちいち うっとうしくない?
>>159 マルチスレッドでも使うけど。
ハードのアクセスなしでシングルスレッドだったら使う必要は無いね。
>>166 修飾した以上違う型なのだから仕方が無い。
169 :
デフォルトの名無しさん :2009/02/25(水) 19:00:09
>>166 volatile で怒られるような使い方は発想が間違っている
マルチスレッドでもハードウェアアクセスでも使ったことあるが、 引数にvolatileつけたことはないな。 InterlockedIncrementみたいに、既存の関数を使うことならあるけど。
171 :
166 :2009/02/25(水) 19:29:44
ふーむ。そうか。 やっぱり俺の不勉強がいろいろ原因クサイな。
>>166 volatileはvolatileとして扱う必要がある。
コンパイルエラーが出てるうちが華。
do-while文とwhile文、どっちがコンパイラが最適化しやすいとかありますか? (処理の都合上明らかにどっちかのが自然に書けるという場合でなく、同じくらいだとしてです。)
>>150 boost使わない場合、ひねくらずにtypeidで型区別して関数に渡せばいいんじゃね?
あんまり美しくないけど、コードはシンプルになるはず
template <typename T> Sample_Class(T value)
{
std::string valueTypeName = typeid(value).name();
if( valueTypeName == typeid(int).name() ||
valueTypeName == typeid(long).name() ...) // unsigned などもチェック
{
funcInteger(); // 整数用関数
}
else if( valueTypeName == typeid(float).name() ...) // double もチェック
{
funcDecimal(); // 小数用関数
}
else
{
assert(!"invalid type");
}
}
175 :
150 :2009/02/25(水) 21:01:26
>>174 あ〜typeidね。
なるほど。
ただ、俺としてはコンパイルエラーないしリンクエラーで検出したいってのもあったんだよね。
クラスの命名基準ってなんかあったっけ?
短すぎず長すぎず、名前で何をするクラスなのかが一目瞭然である事 人の名前を使わない事 誤解や差別を意識させるような単語は使わない事 唯一無二の名詞形であり、スペルミスを引き起こすような単語は避ける事 自分の子供に名前をつけるときと同じくらい悩んで命名する事
178 :
デフォルトの名無しさん :2009/02/25(水) 22:14:15
hage
使い捨てRAIIクラスの命名には困る HogeManagerとかHogeRAIIとかHogeAutoとかHogeUserとかHogeScopeとかHogeSafeとかHogeFinalとかHoge_とか いろいろ試したがどれも気持ち悪い 今はとりあえずHogeHolderに落ち着いてるが、やっぱりしっくり来ない
命名って難しいよなぁ プロジェクトによって変わったりもするし うちはメンバ変数は variableMember_ みたいにしてるけどほかはどうなんだろう
>>167 マルチスレッドではvolatileにしないで排他をかけるべき
たとえread、writeの関係であっても
排他をかけることでほとんどの処理系では
その辺の最適化の抑制をしてくれる
つーわけで普通のアプリでvolatileを使うことはまずない
・ volatile オブジェクトは volatile メンバ関数か const volatile メンバ関数しか呼べない ・ volatile コピーコンストラクタ、volatile 代入演算子は暗黙に作成されない クラスオブジェクトを volatile にする際の注意点な。 まああんまクラスオブジェクト自体を volatile にすることはないが、 構造体くらいならあるかもしれないな。たまには。
void Foo::bar() volatile{/*...*/} って一瞬ギョッとするよな 見慣れないから
class Foo { public: Foo() : m_n(0) { } explicit Foo(int n) : m_n(n) { } Foo(const volatile Foo& foo) : m_n(foo.m_n) { } void operator=(const volatile Foo& foo) volatile { m_n = foo.m_n; } volatile int* Get() volatile { return &m_n; } const volatile int* Get() const volatile { return &m_n; } private: int m_n; }; ああ面倒くせえ。 operator= の戻り値の型を volatile Foo& にしたら、 foo2 = foo1; と書いただけで volatile Foo& を誰も参照してねーよと警告出しやがるし。
>174 type_info::nameは、クラスの比較用としては使い物にならないので止めたほうが良いよ。
g++にて std::string str; long num=std::string::npos; if(num>0){str="num>0";}//@ if(num<0){str="num<0";}//A if(num==0){str="num==0";}//B こうすると確かにAが実行されるんだが、numをlong型からlong long型へ変更して std::string str; long long num=std::string::npos; if(num>0){str="num>0";}//@ if(num<0){str="num<0";}//A if(num==0){str="num==0";}//B とするとなんとAが実行されてしまう。 どうにかならない??
何を言っているのかわからないことだけはわかった。
どうにかしたらどうなってほしいんだ?
>>173 通常は、do-whileの方が初回の比較がない分だけ無駄の少ないコードになることが多い。
しかし、iccのようにforの最適化を重視しているコンパイラの場合、forで書く方がいいかも知れない。
詳しくは最適化スレで。
>>187 要約
「(charがsignedな環境で) charに代入した0xFFは0より小さいのに
intに代入した0xFFが0より大きいと判定されるんだけどどうにかならない?」
と言ってるのと同等。
どうなって欲しいのかは不明。
staticメンバ関数を利用するメリットってあるんでしょうか?
192 :
191 :2009/02/26(木) 06:43:25
すいません スレ移動します
193 :
186 :2009/02/26(木) 12:21:36
みんなホントごめん。 書き間違えた・・・。 g++にて std::string str; long num=std::string::npos; if(num>0){str="num>0";}//@ if(num<0){str="num<0";}//A if(num==0){str="num==0";}//B こうすると確かにAが実行されるんだが、numをlong型からlong long型へ変更して std::string str; long long num=std::string::npos; if(num>0){str="num>0";}// if(num<0){str="num<0";}//A if(num==0){str="num==0";}//B とすると@が実行されてしまう。 どうにかならない?? だった。
194 :
186 :2009/02/26(木) 12:30:48
つまりnumが short型→num<0 int型→num<0 long型→num<0 longlong型→num>0 となるんだか、どうして??
npos == 0xffffffffUL だと仮定すればすべて納得がいく
ありがとう! 読んでくる。
一般的な実装だと、std::string::nposはsize_typeだな。 で、size_typeはsize_tだからunsigned(long)だと。
なるほど、gccのnposの定義はこうなっているな。 -- // Data Members (public): // NB: This is an unsigned type, and thus represents the maximum // size that the allocator can hold. /// @var /// Value returned by various member functions when they fail. static const size_type npos = static_cast<size_type>(-1);
すると、つまりは std::size_tがunsigned longでありunsigned long longでないことから ビット表現の都合上std::string::nposをlong longにキャストしても-1にはならなかったということか。 もしもstd::size_tが(というかnposが)unsigned long longで定義されていたらlong longにキャストすると-1に等しくなったであろうと考えて正しい?
>>201 正しいかどうかに関わらず、nposを汎整数型に代入しちゃダメだろ。
C++の鉄則、表現方法ではなく型を信じろって奴ですね。
21.3にbasic_string<charT, traits, Allocator>::nposはAllocator::size_type型で-1とあり 20.1.6でAllocatorのsize_typeはunsigned integral typeとある。
だったら Allocator::size_type 型で受け渡しするべき。 勝手にキャストしちゃらめぇ。
206 :
デフォルトの名無しさん :2009/02/26(木) 15:38:48
どうやって unsigned が -1 になりえるんだろうな 妙な話だ
207 :
201 :2009/02/26(木) 15:41:03
じゃあ 関数foo()の戻り値の型が、諸処の周辺の事情によりどうしても long long にせざるを得ない状況でstd::string::nposをreturnしたい場合は戻値側でどうすりゃ良いと思う? 単に-1をリターンするか。。。
>>207 戻値側って何だw
まあとにかく-1が返る状況がそれしかないならそれでいんじゃね?
それでいいんじゃない? っていうか、標準を無視するなら何をやっても一緒。 関数の仕様のところに明示しておいて 後は呼び出し側の責任ってことで。 ま、そのうちそんな関数は無視されて 個々の開発者が独自の関数を書くようになる。
>>206 unsignedがsignedで表現できない場合, 変換は処理系に依存するらしい
211 :
デフォルトの名無しさん :2009/02/26(木) 18:08:02
あるcppファイルから別のcppファイルの変数を使いたいんですけどexternしかありませんか? 同じ変数名を使ってるcppファイルが他にもあるので、そちらも影響してしまいますよね?変数名を変えてexternしかないですか?
namespaceで括れば?
つか「cppファイルの変数」て。 グローバルか?グローバルなのか?
214 :
デフォルトの名無しさん :2009/02/26(木) 18:45:06
namespace・・・難しそうですね というかexternの使い方もよくわかっていません 内容はmain.cpp do.cpp main.h do.hとあり、 do で処理をしている変数でbool型、これをmain.cppでifの条件にしたいのですが、さっきからやっているのですがうまく動きません externはどのファイルで宣言、初期化するべきなのでしょうか?
C++は、名前空間では3倍にパワーアップできるのだ
俺も最初C++を学んだとき(つってもそんな昔ではないが) 名前空間 という名称を見てさぞかし難しいんだろうなと思っていた時があった。 …今思うとテンプレートの方が圧倒的に難しい。
構文エラー : ';' が、識別子 'Name1' の前に必要です。 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません 'Name1' : 関数定義のようですが、パラメータ リストがありません。外見上の本体をスキップします。 'Name1' : この名前を指定された名前空間は存在しません。 なんで?
>>219 それが再現するソースを見せろ
話はそれからだ
ソースを見せるのだ、ルーク! いっぱいエラーが出るときは大体1行目がその本体。 そして「 ; が識別子の前に」というエラーが出るときは どこかでステートメント末尾の ; を付け忘れている。 一番多いのがクラス定義の末尾の ; 。 class hoge { }; を class hoge { } と書くとそんなエラー。 C++ のエラーはわかりにくい。
まんまVC++っぽいなぁ 文字コードが混ざったりしてるんじゃね?
てかtrueが入った時に反応してないっぽい 条件をfalseにしたら動く その変数はdo.cppのクラスのプロテクト関数のifの中でtrueが入るようになってるし、そのtrueを使って動くdo.cpp内の箇所も正常に動く その箇所が動いたらfalseが入るようになってる なにかおかしい?
namesapce Name1 { void Func() { } } 普通にこんな感じで囲っただけだが ヘッダファイルでやったらエラーが100個ぐらい出た ちなみにmainではNamea::でなくて::変数にしてた
>>210 それ逆。
signed→unsignedは定義されている。
その定義で、-1を符号無し型に変換すると、変換先の符号無し型の最大値になる。
226 :
201 :2009/02/26(木) 20:28:46
>>224 >namesapce Name1
馬鹿?
>224の6文字目をよく見ろ、間抜け。
なんでこの阿呆は断片しか張らないんだ? つーか、なんでこの戯けは初心者スレに行かないんだ?
じゃあ、以降は放置ってことで^^
おお、本当だ、でも 'Name1' : この名前を指定された名前空間は存在しません シンボルは名前空間 'Name1' 内で定義できません は残った、何も使ってないけど
>>228 >なんで?
エラーメッセージすらはらずに何で?って聞くなヴォケ
人に聞く場合は、問題が再現する最低限のソースをはって
エラーメッセージも添えて出す物だ。
てかnamespace使ったらうまくいくことは高確率で確定してるのか? externで呼び出すことはできてるんだが同じことじゃないの?
違う変数作って同じようにextern作ったらできた 予想では呼び出すのが多すぎたり同時なので一方で使えなかった どう?
>>236 もうみんな呆れてレスが付かねぇなw
>予想では呼び出すのが多すぎたり同時なので一方で使えなかった
君はマルチスレッドで処理しているとでも言うんですかな?
>>234 が言ってるように、再現するソースを見せろ。
標準のC/C++においては、どんなに長い関数名でもおkですか? もっと一般的に、トークンに文字数制限はありますか?
規格上、識別子とマクロ名の長さは1024文字までは保証されてる。
>>239 ありがとう。
長い。心配要らなかったな。
たった1024文字〜
1025文字以上の識別子やマクロを定義するバカはプログラミングの世界から即刻足を洗った方が良いから大丈夫だ。
1024文字の識別子なんてコピペするのも大変だろう
カオスなテンプレートだと実体化したらそれくらい行っちゃうんじゃないの
えー C++はともかく、C89においては、 内部リンケージで32文字 外部リンケージは8文字 しか保証されてなかった記憶があるけど。
それは、テンプレートというかプリプロセッサのほうでは テンプレートの場合は、コンパイラの再帰の段数制限がボトルネック
>>246 >>コンパイラの再帰の段数制限がボトルネック
そんなんあるの?初耳です。
248 :
238 :2009/02/27(金) 00:32:37
>>245 私もC言語はなんか短そうで不安だったので、
まあC++しか使わないんでC++に限った質問にしました。
あるよ。VCなら #pragma inline_depth(255) #pragma inline_recursion(on) g++なら -ftemplate-depth BOOSTだと、使うライブラリによっては必須
250 :
247 :2009/02/27(金) 00:40:55
>>249 探してみました。
GNU コンパイラ集(GCC) の使い方と移植について
http://www.sra.co.jp/wingnut/gcc/gcc-j.html -ftemplate-depth-n
テンプレートクラスの実体化の最大の深さを n にする。テンプレート実体化の深さは、テンプレートクラス実体化の際に無限に再帰が起こるのを検出するのに必要である。ANSI/ISO C++ に適合するプログラムは、17 より大きい最大の深さに頼ってはならない。
17って…なんでまたそういう現実的に問題になりそうなところで手を打っちゃうんですかねぇ。
>>248 なにが「C++に限った」だ。
てめーが「標準C/C++」と書いてるから、
(ここがC++のスレにもかかわらず)「Cでは云々」って突っ込みが入ってるんじゃねーか。
てめーでどんな質問を書いたか、もう一遍読み直せボケ。
>>225 signed->unsignedは書くまでもないことだし
質問者は質問文もまともに書けないことが多いので回答者は 質問文を修正したうえで、質問者の意図する内容を正しく回答してください。
後のエスパー誕生である
質問用のテンプレでも作ったほうがいいんじゃないかなあ 相談はフリースタイルで問題ないけど
class PointContainer{ public: virtual int getPointX(unsigned int index) = 0; virtual int getPointY(unsigned int index) = 0; virtual unsigned int pointsNum() = 0; }; この構造体に仮想デストラクタは必要ですか?
使い方による
使い方 void hoge(){ struct local:public PointContainer{ double *x,*y; }; }
Shift Enter押しちゃう癖が・・・ 使い方 void hoge(){ struct local:public PointContainer{ double *x,*y; local(double *x,double *y):x(x),y(y){} 関数をオーバーライド }; vector<double> x,y; piyo(local(&x[0],&y[0])); } void piyo(PointContainer& pc){ 点情報を読み取る } こんな感じです
その使い方なら必要
そうですか、ありがとうございました。 ところで、何故必要なのでしょう?
必要ないよ。 あと一時オブジェクトは非const参照引数に渡せないと思った。 VCでは渡せちゃうけど。
std::string()という式は、空の文字列が返ることが仕様により保証されている…よね?
>>262 んん?どっちなんでしょう・・・。自分的には要らないかなと思ってたんですが・・・
ちなみにBCCで一時オブジェクト渡せました。そういえば、いつもならエラーになるはずなんだけど、何でだろ・・?
どんなときに仮想デストラクタじゃないと問題なのか理解してれば分かるだろ。 理解があやふやならちゃんと調べた方がいい。
理由はともかく、結論だけ言えば、 継承させるつもりがある: publicで仮想かprotectedで非仮想 継承させるつもりがない: 非仮想、公開は好きにしろ
>>263 されていたような気がする。…気がするだけ。
>>264 この機会にデストラクタを学んでおくといいかも。いつか役に立つ時が来る。
デストラクタって言うか、仮想関数の話ですよね? 基底でvirtualにしてないと、仮想関数テーブルが派生クラスの関数に上書きされちゃって 実行時にテーブルを辿れない。実行できない だから、デストラクタでやること無いなら(メンバもPODなら)仮想デストラクタにする必要無いかなと 思ったけどこれで合ってます?
特別なデストラクタが必要なのは、メモリ開放とかの後処理を要するクラスの場合。 仮想関数が必要なのは仮想の振る舞いが必要なクラスの場合。 local を PointContainer のポインタを介して削除する可能性がないなら 「仮想の」デストラクタはいらない。protected 非仮想で十分。 そうでないなら public 仮想にする必要がある。 問題は、デストラクタの中身。 PointContainer が後処理を必要としないクラスの場合、 動作内容はデフォルトのデストラクタと同じ「空」で十分だが、 デフォルトのデストラクタは public 非仮想なので 基底クラスのポインタを介した削除を許しながら、 動作は未定義というすばらしいことに。 結論:基本クラスのデストラクタは「必ず」記述しましょう。 (ハブサタ本の50項)
271 :
デフォルトの名無しさん :2009/02/28(土) 01:15:28
> local を PointContainer のポインタを介して削除する可能性がないなら > 基底クラスのポインタを介した削除を許しながら、 矛盾してるやん
そうだよ。 デフォルトデストラクタを使うと矛盾するから「必ず」記述しましょうって話になるわけで。 詳しくはハブサタ本50項。
273 :
デフォルトの名無しさん :2009/02/28(土) 01:25:11
基底クラスのポインタを介して削除する可能性がないなら非仮想public(つまりデフォルトのまま放置)でも問題ないだろ つーか、ここまで言わないとわかんねえ?
ハブサタ本っていっぱいあるんだが…
>>273 だから、だめなんだって。
だめな理由はハブサタ本、C++ Coding Standards の 第50項にびっしり書いてあるよ。
っていうか、読んだこと無いのか?
Effective C++にも書いてあるだろ・・・
それは可能性が無いのではなくて、 基底クラスのポインタを介して削除しないで下さいというお願いしているに過ぎない。 しかも、無視される可能性はある。 安全性という観点から言えば厳密には問題があるが、 実際問題それで大丈夫な場合もあるし、 パフォーマンス上致し方ない場合もある。
>>276 そういう例外についてもハブサタ本の50項にびっしり・・・
だから何度も「ハブサタ本」と書いたんだが、
この程度の本も読んでない人いるのか?w
分かりました。今までどおり仮想にします。ありがとうございました。
279 :
デフォルトの名無しさん :2009/02/28(土) 01:40:36
> だから、だめなんだって。 説明になってねえぞ 自分の言葉では表現できないと見なしていいんだな?
protected 非仮想にすれば基底クラスのポインタを介して削除することは不可能だよ。
>>279 いいよそれでもうw
ともかくC++ Coding Standardsの50項読んでくれw
つか、その程度も読んでなくてここで回答している奴いないよな?w
不可能ではない
C++ Coding Standardsをハブサタ本って言われると死ぬほど違和感があるんだが
いつもboost::shared_ptrを使うのなら常にpublic非仮想で問題ない
> 不可能ではない 説明になってねえぞ 自分の言葉では表現できないと見なしていいんだな?
共著者のテンプレート厨さんも忘れないであげてください
>>285 不可能ではないと言ってるだけだ
privateデストラクタのポインタを外から合法的に取るトリックがあるだろ
>>287 説明になってねえぞ
自分の言葉では表現できないと見なしていいんだな?
289 :
デフォルトの名無しさん :2009/02/28(土) 01:47:43
> いいよそれでもうw あっそう いるんだよねー、これからって時に議論を放棄する奴って 相手するの馬鹿らしいから死んで欲しいぜ
ハーブサッターといわれれば、普通Exceptionalだよなぁ Coding Standardsを代表作のように言われるのはちょっと…
消去済のベースにアクセスされる可能性がまったくないprivate以外ならvirtualってことかなるほろなるほろ
スコットメイヤーズがEffective STLで 信用なら無い場所に出入りしていると 信用ならない人に出くわすと書いてるけど まったくそのとおりだな。 こんなところの書き込みを信じるより ちゃんと本読んで解決したほうがいい。
C言語で使われる構造体と互換性と保ちつつクラス化したい場合には 非仮想デストラクタをもちつつ派生する必要があったりするんだよ。 かなりな例外的な状況だが、MFC の CPoint とかまさにそういう例だな。
そう思うなら来なきゃ良いのにw
CPointがあれで大丈夫なのはPODだからだし あんまり今の話とは関係ない
とりあえず、Effective C++はみんな読んだよな?
生半可な知識で解答する人たちの巣窟です^^
まあ、別にメイヤーズやサッターは神じゃないので 彼らも間違えることはあるし、正しいとしてもあらゆる場面で当てはまるとは限らないし
>>295 POD だから大丈夫とか、頭大丈夫か?
少なくとも俺よりは賢いので信じてる
C++ Coding Standardsの冒頭にも盲目的に受け入れるのはやめろと書いてあるしね でもまぁほとんど正しい ケースバイケースだが例外はやはり例外だ
例外0だ! と言ってるようなのはアレだがね
>>295 PODなら自分と全基底クラスのデストラクタがデフォルトなんだから
どれが呼ばれてもどうせ何もしないので問題ない
そしてPODだからsizeof(tagPOINT)とsizeof(CPoint)さえ同じなら平気
なんか間違ってるか?
非PODなら後の方の条件は成り立たないだろ
Coding Standardsは読んでないな ぱっとみ内容がつまらなかったよ Exceptionalやらを読んだ方がよほどためになると思うが
読んでない人の感想はどうでもいいです。
まあEffective,MoreEffectiveとExceptional三部作を全部読んでれば 必要ない本ではある>Coding Standards ほぼ全部この5冊のどっかに書いてることだから
Coding Standardsはインデックス集で各書籍への参照が書かれているから 「Coding Standardsは読んでないが xx は読んだ」というと 「その本の nn ページを読め」と返されるぞ? 恐ろしい武器だ。
Cording Standardsはガイドラインだよ。ざっと眺めるのがよろし。
ほんとにEffective C++とかよんだんかい、もまいら。
Effective C++読まずにC++使ってる奴なんかいるわけないだろ 自殺志願者でもなけりゃ
第14項(第2版だけど)を大声で読み上げてみてw
あんな本に4000円も出せるかよ …2版持ってるから3版買いづらいよ。目次見る限り常識的なことしかなさそうだし 周りの誰かに借りようと思っていたが、周りの人間もそう思っているのか誰も買っていない 皆で牽制しあっている
リソース管理クラスのコピーの振る舞いはよく考えて決めよう (第3版)
基底クラスには仮想デストラクタを持たせよう これを"墨守"する奴は馬鹿だろ
3版は「ポリモーフィズムのための基底クラスには」になってて 仮想デストラクタにすべきでないケースについても書いてるけど 2版持ってないけど、ひょっとして書いてないの?
おまえらの言うことよりメイヤーズの言うことを信じるわw
カスプログラマほど自尊心が大きなものだということがわかりますネ^^
なぜこう荒れるかね・・・
321 :
デフォルトの名無しさん :2009/02/28(土) 05:45:16
カスタネットって同じ事しかできないんだな
322 :
デフォルトの名無しさん :2009/02/28(土) 05:50:47
業者が自分トコの本を必死に宣伝するスレはここですか
>>303 tagPOINT は POD だが CPoint は POD じゃないから、
デストラクタは空っぽだけど、規格上動作は未定義じゃね。
デストラクタの動作をきちんと正しく言える人は居ないのかな。それがあればもう解決しそうだけど
325 :
デフォルトの名無しさん :2009/02/28(土) 10:50:51
「正しく」って何か難しいことでもあるの?
>>316 Effective C++の改訂第2版には
C++ Coding Standardsにあるような例外の記述はないよ。
もう10年も前の本だからね。
いくつかの項目は役に立たなくなってる。
アンドリューハントの達人プログラマーじゃないけど
第2版の内容しか知らない人は時代遅れのカスプログラマと見ていい。
327 :
デフォルトの名無しさん :2009/02/28(土) 13:41:55
例外オブジェクトのないthrow;をcatchできますか?
328 :
デフォルトの名無しさん :2009/02/28(土) 13:59:53
できます。
例外オブジェクトがないthrow ? そんなのありません。 あるとしたら、何をcatchをするんですか? ないものをどうやってcatchするんですか?
例外の再スローをキャッチするって事じゃないの?
try { throw; } catch(/* ここなんて書くの? */) { std::cout << "catch"; } このプログラムは落ちます。
332 :
デフォルトの名無しさん :2009/02/28(土) 15:56:40
catch(...)
どっちにしても落ちる
throw; はアクティブな例外を再スローするんだから アクティブな例外がないところで呼んだらそりゃ落ちるわな
>>334 それが、再スローでないのにthrow;使っているコードを見てorz
それを何事もなく処理するVCが恨めしい。
別に文法に違反してないでしょ terminated()が呼ばれる事になっているし なぜVCのせいにするのか訳わからん
確かにgcc 4.1 は catch(...) で捕捉できないね これは言語仕様の不備なのかgccのバグなのか いずれにしても素のまま実装しているgccは、よろしくないと思われるが
terminate()だった
339 :
337 :2009/02/28(土) 16:42:10
ごめん terminateが呼ばれるって、言語仕様で決まってるらしいね
340 :
名無しさん :2009/02/28(土) 17:02:40
SQLサーバーに問合せし、結果をフェッチする場合など、返ってくるデータ数が分かりませんが、 SQLFetchをwhilede一度回して行数を確認して、もう一度Fetchしなおすならnewで エリアを確保できるでしょうが、このエリアは関数内しかスコープがないので クラス化して、メンバー関数としたい場合は、vectorを使うしか方法は無いんでしょうか?
ダメだここの連中。
・濃度が未知の集合を低コストでスコープ間で持ちまわりたい ・ただし濃度はある程度低いコストで既知にすることができる そういう要件ならvectorでいいだろうね
音楽再生プレイヤーを作りたいのですが、 「L−R」みたいに左右の音の位相を打ち消すソフトってC++で作れませんでしょうか。
そういう波形作ればいけるんじゃない? ハードレベルが対応できるかは知らん
346 :
デフォルトの名無しさん :2009/03/01(日) 01:25:36
>>343 リニアPCMに直してサンプリング単位にL-Rするだけだろ?
そもそもC++で作れないソフトなんてほっとんどないだろ。 作れないのはプログラマ(俺含め)の方であって。 …強いて言うなら早さを極限まで追求するタイプのソフトくらいか。
__asm
>>349 ディフォルト・コンストラクタの呼び出しの表記上の問題:
H h(); // ← H h = H(); のつもりなのに関数の宣言だとみなされてしまう
は、C++0x的には
H h{};
と書けば解決するのかな。
おまいは defaultをいつも「ディフォルト」と言ってるが desktopも「ディスクトップ」と呼ぶのか?
あとは351が後出しの釣り宣言で自己のダメージ広げるのを待つばかり。
えー、もしかしてディフォルトという読み方を標準的な日本語(外来語)とするために そんなに頻繁にディフォルトディフォルトディフォルトと繰り返してるんですか? まずこの板の名無しから変えるよう努力したほうが コミュニケーション能力を磨くより有用かもしれませんよ。
釣りを封じられたので論点そらすほうに走ったようですね。
358 :
デフォルトの名無しさん :2009/03/01(日) 11:22:27
>>357 論点なんかずらしてないよ。
日本語では「デフォルト」を使うべき、という主張は全然変わらないから。
普通の日本人はcameraをキャメラなんて言わないし。
心の中でそう思っていても、他人とコミュニケーションを取るために必要だから。
そういう「共通用語として使えることの重要性」が認識されているから
デザインパターンなんてものが生まれたわけだけど、聞いたこと無かったら調べてみるといいよ。
360 :
デフォルトの名無しさん :2009/03/01(日) 11:37:17
ディザインパトゥン
>>359 要約すると、デザインパターンなのかディザインパターンなのかが問題ってこと?
いや、日本にはC++をbetterCとして使う奴しかいないんだから、クラスや継承なんて使うなってこと。
>>359 desktopはディスクトップとは読まないからね。
そもそもディという発音自体、無いからね。
これ覚えておこうね。恥かかずに済むから。
「desktopも「ディスクトップ」と呼ぶのか?」とか、あり得ないからね、質問として。
いまいち流れがわかりづらいな。
1)
>>351 は最初、defaultをディフォルトと読むのは、desktopをディスクトップと読むのと同様の
「間違い」だと指摘していたが、そうではないことが
>>353 のレスで理解できたので、
慌てて路線変更して「共通性から離れて本格的な発音にこだわることの問題点」を指摘していることにし始めた。
2)
>>351 は、初めから「共通性から離れて本格的な発音にこだわることの問題点」を指摘していたのだけど、
desktopをディスクトップと読むのもその仲間(「本格的な発音」を追求した書き方)だと勘違いしていたので、
そういう意図で発言しているとは誰にも思って貰えなかった。
3)
>>351 は初めから「共通性から離れて本格的な発音にこだわることの問題点」を指摘していたし、
desktopをディスクトップと言うのは、それとは次元の異なる「単なる間違い」であることもわかっていたが、
どういうわけか、まったく関係の無いタイミングでdesktopを引き合いに出すという電波質問をしてしまった。
どれなんだろう。
> そもそもディという発音自体、無いからね。 ディフォルトもだめなん?
>>365 desktopという単語の中に、そんな音は無いという意味だろ。
>>353 のwavでは
defaultはデフォート
deskはデャースクって聞こえる
むしろ、わざわざディフォルトと書く理由を知りたい
もうkatakana語排除して直接alphabet綴りで書くようにしようぜ
C++の予約語はアルファベットで書くけど、デ(ィ)ストラクタには予約語が無い。object pascalだったら良かったのにね。
>>368 たまたま手についちゃった書き癖じゃないの?
>>356 が興奮気味に書いてるキャラ設定みたいな理由は無いだろう、たぶん。
そういえば、C++3rdの翻訳、detailをディティールって書いてて、違和感あったな。
そうは発音しないと思うんだけど・・・俺が知らないだけ?
でも、あれだって少なくとも「標準的な日本語(外来語)とするために」活動してるわけではないだろうw
警告するのワーンだけは、自分の中で許せないと思っている コミュニケーション大事だがら状況に合わせるけどね
iknowで知らべたらディーテォって聞こえた 覚える為にはスペルと対応が取れてるディ(de)テイル(tail)って読みが都合が良いんだけどさ
>大事だがら さては道産子だな?(いや、道産子言葉俺は知らんけど)
>>373 辞書引いて発音記号見たら
2種類の発音があることがわかった。
ただし共にtailの部分はテイルだった。
template <typename T> class Myclass { public: template<char ch> T foo() const; }; template<typename T>template<char ch> T Myclass<T>::foo() const {std::cout << "T and char " << std::endl;return 'c';} として、 int main() { Myclass<char> hoge; hoge.foo<5>();//27行目 return 0; } としてみました。 すると Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland エラー E2235 〜.cpp 27: メンバー関数は呼び出すかそのアドレスをとらなければならない(関数 main() ) エラー E2188 〜.cpp 27: 式の構文エラー(関数 main() ) *** 2 errors in Compile *** と言われてしまいます。しかしg++でコンパイルすると問題無くコンパイルできました。 私のどのあたりの記述が悪いのでしょうか?
同じ要領で \di-ˈtāl, ˈdē-ˌtāl\だから、 敢えて書くなら「ディテイル」か「ディーテイル」ってことになりそうだ。 # 前者はテイにアクセント、後者はディーにアクセント。 でもまぁ、「ディテール」は許容でいいんじゃない? 「ディティール」は許容したくないけど。
>>376 コピーライトを見ると2000年だから、bccは腐ってるんじゃないの? もっと新しいバージョンはないのかな?
メンバテンプレート関数の特殊化ができない有名なバグだな その時期のBCCはマジ糞だからC++ならVC2008とか使った方がいいよ
>>378-379 ありがとうございます。
私は職業プログラマではないので単なる趣味のレベルなのですが、初めてコンパイラのバグに出会ってちょっとうれしいです。
char str[20]; void setStr(char *test){ str = test; } みたいなことってできないんでしょうか? 20文字以内の文字列をstrに突っ込みたいと思ったんですが・・・。
>>381 アドレスとポインタを理解してから考えてみれば分かると思うが、それはできない。
C言語レベルで相当理解が足りないので、何か本を一冊買って通読したほうがいい。
>>382 何故できないのか説明してみろよ?
偉そうに嫁とかいってるなら。
>>383 お前はアドレスにアドレスが代入できると思うのか?
型が違っていて暗黙の型変換が定義されていないから(←そのまま)
>>383 それよりお前が説明してみれば?
教えて欲しければそう言え
>>387 そうか。悪い。人違いだ。
そして俺もちょっと言い方がきつかったな。すまない
389 :
380 :2009/03/01(日) 13:36:49
>>378-379 bccの最新版をDLしてきました。
…が、古い版と全くおなじでした。バイナリレベルで同じ物が手に入りました(笑)
bccは諦めてg++を使います。
VC2008も挑戦してみます。
冷静に考えてみると=でコピーができるなら strcpyとかなんて関数ありませんよねー・・・C++なので素直にstring型使ってきます
391 :
388 :2009/03/01(日) 13:43:30
>>390 配列の名前はその先頭アドレスを指す。
よってstrはアドレスであり、それを左辺に持ってきて代入しようとしても
極論すれば100=〜としているようなものだから不可。
てなところか。
まあstd::stringが使えるならそれでいいな。
宣言した時点ではstrにはNULLが入ってるっけ?
393 :
392 :2009/03/01(日) 13:45:50
strじゃないtestのほう
>>392 入ってないよ。
C/C++はそういう余計な遅延になりそうなことはデフォルトでしたがらないからね。
char str[20];
void setStr(char *test){
std::cout << reinterpret_cast<unsigned long>(test) << std::endl;
}
としてみるとわかる。
時々悩む事 void *test; *をvoid側につけようかtest側につけようか・・・
>>395 あるあるw
人によって好き嫌いあるよね。
voidの場合はともかくintだとすれば
int *a,b,c;
の様に宣言するとaだけがポインタだとわかりやすい。
しかし型という観点からはint *型なんだから、int*とくっつけるべきと言う考えもあるよね。
折衷案の
int * hoge;
はやだな。
>>381 char str[20];
void setStr(char *test){
for(int i = 0; i < sizeof(str); i++)
str[i] = test[i];
}
>>381 std::string str;
void setStr(const std::string& test){
str = test;
}
>>397 恐ろしいバグ持ちコードだな・・・
testのサイズがstrのサイズ未満だったらどうなるよ?
>>399 char str[20];
void setnStr(char *test, int n){
int size = sizeof(str) < n ? sizeof(str) : n;
for(int i = 0; i < size; i++)
str[i] = test[i];
}
401 :
394 :2009/03/01(日) 14:15:22
>>399 俺もそう思った。
…が、
「20文字以内の文字列をstrに突っ込みたいと思ったんですが・・・。」
という仮定があるようだ。ちゃんと文字数チェックしていればバグでも脆弱性でもない。
>>399 char str[20];
void setStr(char *test){
for(int i = 0; i < sizeof(str) && test[i]; i++)
str[i] = test[i];
str[i-1] = '\0';
}
char str[20] = {'\0'}; char *pStr = str; void setStr(char *test){ std::size_t size = 0; static const std::size_t limitSize = 18; // ラストのヌル文字考慮 while( *pStr++ = *test++ ){ if( size++ >= limitSize ) break; } }
char str[20]; void setStr(char *test){ if(test == NULL) return; for(int i = 0; i < strlen(str); i++) str[i] = test[i]; test[i]='\0'; }
sizeofを使うのが間違ってる
#include <cstring> char str[20]; void setStr(const char *test){ strncpy(str, test, sizeof(str)); }
配列データを宣言時に初期化しないのはバグの温床
>>405 のように最初のチェックでtest==NULLの時、str[20]はゴミだらけなんだぜ?
char str[20] = { '\0' };
このたったわずかな宣言だけで、安全性を高める事が出来る
まぁC++じゃ配列なんて使う方が間違っている 普通はコンテナ。
>>408 速さを求めないなら配列よりコンテナだよなやっぱ。
配列データを宣言時に初期化するような軟弱なコードでいいなら、C++なんて使わずにC#を使えばいい。
>>401 まてまてw
「20文字以内の文字列を〜」は、*testの事を言ってるんだろう?
渡された*testがtest[3]だとしたら
for(int i = 0; i < sizeof(str); i++)
str[i] = test[i];
このコードでiが2以上の場合どうなるかはわかるよな?
簡単なネタには喰いつきがいいなw
413 :
401 :2009/03/01(日) 14:42:42
>>411 素で間違えた俺がいる
不正なアクセスだ
しまった
コンテナが遅いとか言ってる池沼がいるスレはこちらでしょうか?
素直に自分のミスを認められるプログラマは成長する。
>>413 には期待してる
関数外で宣言されたグローバル変数って中身0で初期化されてなかったっけ?
char str[20]; void setStr(char *test){ str = test; } 関数外っぽいから= { '\0' };いらなくね?
420 :
デフォルトの名無しさん :2009/03/01(日) 15:28:02
あーゆー手合いは、それでも = { '\0' }; を書くだろ
空の文字列作るなら="";でいいんじゃないの?
""で充分だろ \0とか書くと、逆に紛らわしい
絶対間違えて'0'と書く奴が出てくるしな
="\0"
426 :
デフォルトの名無しさん :2009/03/01(日) 21:26:11
C++の中から、monutなどのshellコマンドを呼び出すことはできますか?
ID:XrL2djEm0のくだらない意見のせいで前スレ
>>1000 がつまらない内容になったな。
>>1 も読めない自称中学生は大人になるまでロムっててね
>>426 man 2 mount
もしくは
man 2 system
あとスレ違い
あ、system(3)だた・・・
>>402 と
>>405 だけどさ、iはforを抜けた時点で破棄されるんじゃないの?
VC6++なら破棄されないんだろうけど。
破棄されるね。
破棄というかコンパイル通らないんじゃ?
VC6だとしても
>>402 はtestが空の場合やばそうだし、
>>405 はstr[20]に代入するような気がするんだが
ある関数がinline展開できるための条件(再帰でないなど)があったと思うのだが、 なんか検索してもいまいち引っかからん。 誰かinline展開できるための条件(ないしそれが分かるいいサイト)教えてくれない?
コンパイラ次第。一般的な条件なんてない。
>>436 そうなんか。
そして俺みたいにinlineについて詳しくない人は
無駄にinlineとか書かずにコンパイラの最適化能力に任せる様にした方がいいの?
using namespace std; ってやるのってどう思う? 俺は意地でも名前空間、stdは全部std::って付けてusingは一度も使わない様にしているんだが。
俺は関数スコープでならたまに使う あとswapする時とか、隠蔽されたメンバ関数を引っ張り出す時とか、 boostとtr1のshared_ptrを楽に切り替えたい時とか
>>439 なるほど!
using嫌いだったのだが、ちょっとusing見直した。
サンクス。
>>439 2行目はusingであって、using namespaceの出番ではないな。
442 :
440 :2009/03/02(月) 00:06:56
>>441 まあ2行目は俺もusing使っていた。
using namespaceとしては、3行目は気がつかなかったよ。
>>437 ハーブサッターの・・・
と思ったけど、またキモい人が噛み付いてくるかもしれないからヤメた。
ヘッダに定義を書きたいかどうかをinline付けるかどうかの判断基準にしている。
445 :
437 :2009/03/02(月) 00:42:21
446 :
437 :2009/03/02(月) 00:43:08
J.K.ローリングの小説の主人公
沖縄人。ハブと戦わせるとやたらと強い。
渡辺竜王より強いかもな。
ハブ殺ったーか
勉強すればわかるという回答を延々繰り返す価値があるかどうかの議論もそろそろ必要じゃねw
そういうメタ議論がしたいなら他でどうぞ。
g++で error: `wcout' is not a member of `std'; と言われてしまいます。 #include <iostream> #include <string> #include <fstream> #include <locale> #include <conio.h> で std::wcout.imbue(std::locale("")); と std::wcout << 〜〜; のところで言われます。 ヘッダのインクルードが足りないとかでしょうか?
>453 多分 Cygwin 上の gcc じゃないかと推察するが、Cygwin (少なくとも 1.5) は locale 実装が腐っていることもあり wchar_t 関連は使えない。
g++というよりlibstdc++の話だろうが、 ワイド文字対応が駄目すぎる環境では、wcoutなどはそもそも用意されないようになっている。 例えばCygwinとか。
エスパーワラタ
457 :
453 :2009/03/02(月) 21:29:05
gcc 4.4.3 ubuntu です
458 :
453 :2009/03/02(月) 21:46:46
>>454-455 g++ (GCC) 3.4.5 (mingw special)
でした。
最新版にして来ます。
あと
>>457 はかわいそうな人です。
>>458 >>453 は最初から環境すら書けないかわいそうな脳の持ち主ですね
人のことをかわいそうと言う前に自分のかわいそうな脳をなんとかしたら
461 :
デフォルトの名無しさん :2009/03/02(月) 22:34:41
ubuntu8.10 gcc_g++4.3.2 すみません、教えてください。 今、listをreturnすることはできるのでしょうか? (func()がlistを継承せずに) 下のようなイメージです。 list<int> func() { return list<int> } int main () { list<int> is; is = func(); }
できますよ
できるけど、コストが高くなりがちなんで普通はしないかなぁ
464 :
デフォルトの名無しさん :2009/03/02(月) 22:47:34
できるということですね? すみません、もう少し教えてください。 私は今、mainから、func1()を呼んでいます。func1では、答えを多数発生(場合の数、すべての 組み合わせを発生させるようなもの。例えばclass Xのリスト、list<X> Xsを作る)します。 この多数発生させたXsをreturnさせたい。 さらに言えば、さらにそのlistを作成したい。(Xss.push_back(func1())のようなことをしたいのです。) プロはどうしているのですか?このまま単にコードを書くだけでしょうか? それとも何か別の方法があるのですか? 私としては、mainの見通しが悪くなるので、mainにはあまり2重ループを作りたくないためにこのような 設計を考えています。
プロじゃないけど、list<X>isを参照渡しかポインタ渡しするかな 実体をreturnするのはあり得ないと思う
466 :
461=464 :2009/03/02(月) 23:01:14
ありがとうございました。 とりあえず、ポインタ渡ししてフツーに書くしかないみたいですね。
ああ、だからムーブセマンティクスよ早く来い。
ムーブセ。マン。ティック。
list内包したテンプレートクラス定義してコンストラクタ引数から答えを持ったオブジェクトを普通に作る じゃだめなの?
ムーブ不可の場合はコピーされて、 ムーブ可の時はムーブされんの? >STL
>>470 そうなるみたい。少々無理のあるやり方と考える向きもあるようで。
>>461 まず、mainは代入ではなく初期化にした方が良い。
int main(){
list<int> is = func();
}
そして、このコードがどうコンパイルされるかを確認する。
場合によっては効率の良いコードが生成されているかもよ。
インライン展開してくれるかもね。
474 :
デフォルトの名無しさん :2009/03/03(火) 13:48:16
初期化を = で書くなよ ぼけ
いーじゃん別に
>>474 口ではそういっていてもカラダはfor(int i = 0; i < N; ++i)とか書いちゃうんだろう?
477 :
デフォルトの名無しさん :2009/03/03(火) 14:13:58
何で初期化を=で書いたらダメなの?
479 :
デフォルトの名無しさん :2009/03/03(火) 14:30:52
fusianasan の言ってることをひっくり返してみれ
駄目な理由がさっぱりわからん
違うだろ explicitが付けられるとコンパイルが通らないよ、という意味では?
で?
> コンストラクタと代入演算子が呼び出されると思ってる。 ( ゚д゚)ポカーン いや、いくらなんでもそんなアホは居ないだろう 474先生の詳しい解説まだー?
無理矢理導入したクラスが構造化プログラミングの流れに偏っていた無残りを
間違った方向に交通整理しようとして提唱された中括弧書式優先の書法を
信奉し愛しちゃってるのが
>>474 先生
ここはカスみたいな回答者ばかりなので詳しいことは不明です。
487 :
デフォルトの名無しさん :2009/03/03(火) 17:48:17
=初期化が嫌な人は黙ってexplicitをつければ済むんじゃね? そしてhoge a();で悩むんだな。
489 :
デフォルトの名無しさん :2009/03/03(火) 17:54:07
std::string() で悩んでる香具師いたな
char & c[] = "this is a pen."; c[ 0] = 'T';
474はおそらくlist<int> is = func();がlist<int> is = list<int>(func());と解釈され、 一旦余計な一時オブジェクトの生成が起こるから、非効率だと考えていたのではないかと思う。 けど、それはfunc()がlist<int>型(またはその派生クラス型)以外の場合だけ。 461のfuncはlist<int>を返すから、=で初期化しても、l ist<int> is(func());と同じように直接初期化される。 (8.5 14節 2)にそういう規定があった)
それってコピーコンストラクタを全く理解していないじゃないか
これで見やすい=での初期化が安心してできるわ
(N)RVO
標準C++の環境で std::size_tは必ず何らかの非負整数型(それがunsignedなんなのかは不問として)のtypedefであることは保証されてる? それとも独立した組み込み型であるようなことがありえる?
>>496 そーなんか。
typeだと思ったんだぜ。
どうも。
加算代入演算子 って英語でなんて言う? additional substitution operator こんな風にC++でいろいろと名前を付けるときに英語が分からなくて困る事がしばしばあるんだが、みんなそんな時どうしてる?
500 :
499 :2009/03/05(木) 14:31:15
ああ、ちなみに
>>499 の
additional substitution operator
は適当に俺が直感で訳した物。
501 :
デフォルトの名無しさん :2009/03/05(木) 14:34:37
>>499 まず JIS を見て、それに対応する位置を ISO で見る
502 :
499 :2009/03/05(木) 14:35:27
addition and assignment operators だな
504 :
499 :2009/03/05(木) 14:58:29
>>503 答えまで教えてくれるなんて助かる(> <)
うっうー
あぅあうあー
しーねwwwしーねwwwww
class Derived; class Base { public: Base& foo(Derived x); }; class Derived : public Base { public: Derived(){}; }; という状況で、 Base& Base::foo(Derived x) { this->foo(static_cast<Derived>(x));//@ return *this;//A } と定義した。 ・・・この最後の@Aを1行にまとめることはできない?
基底クラスが派生クラスを知っているのはクソ設計。
>>510 それもそうだな。
なんか問題の部分を抽出したらこうなってしまった。
しかもfooがfooを呼び出す定義になってるし。
てことで修正。
class Base
{
public:
Base& foo(Base x);
Base& bar(Base& x){/*適当な処理*/return x;}
};
Base& Base::foo(Base x)
{
this->bar(static_cast<Base>(x));//@
return *this;//A
}
と定義した。
・・・この最後の@Aを1行にまとめることはできない?
return this->bar(static_cast<Base>(x)), *this;
おやめください。
514 :
511 :2009/03/05(木) 17:08:35
>>512 ・・・た、確かに一行だw
まあ俺の問いも意味不明かも。
すまんな
/*適当な処理*/を private 関数にする。
ねぇねぇ。素人質問で申し訳ないんだけど this->bar(static_cast<Base>(x)); は単に bar( dynamic_cast< Base >( x ) ); じゃだめなんかいのぅ? this-> をつけないと競合する名前があるってこと?
std::wstring wstr; wstr=L"sample"; std::cout << "test1\t" << ((std::wstring(L"sample")==wstr)?"true":"false") << std::endl; std::cout << "test2\t" << ((std::wstring(L"sample")!=wstr)?"true":"false") << std::endl; wstr=L"あいうえお"; std::cout << "test3\t" << ((std::wstring(L"あいうえお")==wstr)?"true":"false") << std::endl; std::cout << "test4\t" << ((std::wstring(L"あいうえお")!=wstr)?"true":"false") << std::endl; こうするとVC2008では test1 true test2 false test3 true test4 false となる。これは正しい。しかしこれをbccでやると test1 true test2 false test3 false test4 true となる。 …これはbccがクソなせいか? g++に至ってはコンパイルすらできないが。
518 :
514 :2009/03/05(木) 18:10:46
>>516 ああ、単にそれでおk。
ただ俺の取り組んでいる本家のソースの方(2ch投稿用に切り出した物ではなく)はテンプレートの関係でthis->をしないわけには行かなかったんで付けてたら、
つい間違って2ch投稿用に切り出した物にまで付けちゃったんだ。
惑わしてすまん。
>>517 g++通ったけどなぁ
バージョンは4.3.3
文字コードがsjisだったりする?
521 :
514 :2009/03/05(木) 18:21:20
>>519 それも無駄キャスト。
本家のソースの方(2ch投稿用に切り出した物ではなく)は他のクラスの引数も受け取れる仕様になってたから
キャストしてた。
…要するに消し忘れ。
>>520 >文字コードがsjisだったりする?
文字コード…g++についてはその辺がhitかも。
とりあえずbccがクソであることは確定して良い?
523 :
520 :2009/03/05(木) 18:27:28
どうでもいいんだろうけど結果はちゃんと test1 true test2 false test3 true test4 false でした
524 :
522 :2009/03/05(木) 18:31:09
526 :
517 :2009/03/05(木) 20:03:21
>>520 g++を現在の最新の
g++ (GCC) 4.3.3
にして
std::wstring wstr;
wstr=L"sample";
std::cout << "test1\t" << ((std::wstring(L"sample")==wstr)?"true":"false") << std::endl;
std::cout << "test2\t" << ((std::wstring(L"sample")!=wstr)?"true":"false") << std::endl;
wstr=L"あいうえお";//17行目
std::cout << "test3\t" << ((std::wstring(L"あいうえお")==wstr)?"true":"false") << std::endl;//18行目
std::cout << "test4\t" << ((std::wstring(L"あいうえお")!=wstr)?"true":"false") << std::endl;//19行目
をコンパイルするも
〜.cpp:17: error: converting to execution character set: Illegal byte sequence
〜.cpp:18: error: converting to execution character set: Illegal byte sequence
〜.cpp:19: error: converting to execution character set: Illegal byte sequence
というエラーになる。
>>520 さんの言う文字コードってのはソースファイルの文字コードのこと?
それなら[Shift-JIS]で [CR+LF]になってる。
>>526 --input-charset指定していないだろ。
>>497 wchar_t は組み込み型だから typedef の証ではない
>>529 wchar_tだけは_tだけど特別なんだろ。
C言語との兼ね合いで。
だめです。
>>517 BCC6.10(最新版)を使うと
true
false
true
false
となった。
534 :
デフォルトの名無しさん :2009/03/05(木) 20:57:20
535 :
497 :2009/03/05(木) 21:35:01
>>529 互換性のために組み込みにするか否かを決める
コンパイラオプションがあったりするよ。
C.2.2.1 wchar_t is a keyword in this International Standard (2.11). It does not appear as a type name defined in any of <cstddef>, <cstdlib>, or <cwchar> (21.4).
537 :
517 :2009/03/05(木) 22:05:59
>>535 そういう話をしている場合でないくらいわかるだろ。
>>539 売り物かぁ。
売り物はもってないんだよねぇ。
BCB買ったはいいけど一度も使ってない ゴメンね
542 :
517 :2009/03/06(金) 01:39:15
みんなありがとう。 俺は最終的には #if defined(__BORLANDC__) 〜 #endif という(最低のw)手段で乗り切る予定。 この辺で寝ないと明日死ぬから寝るけど。
Effective C++第3版のP249に template<typename IterT, typename DistT> void doAdvancd(IterT& iter, DistT d, std::random_access_iterator_tag){ ... } ってあるけど、この第3パラメータって何なの?C++て型情報をパラメータに取れるの? これの呼び出しが doAdvance(iter, d, typename std::iterator_traits<IterT>::iterator_category()); になってて、この第3パラメータは何なの?typenameをつけると型情報が出力されるの?
>>543 オーバーロードの仕組みを使って適切な関数が呼び出されるようにしているだけ
std::random_access_iterator_tag はただの型で、引数名を省略している
呼び出しの方も一時変数を作って渡しているだけで特に変なことをしているわけではない
IterT がテンプレート引数じゃなくて実際の型だったら、そこにある typename は要らない
例えば、以下はOK
doAdvance(iter, d, std::iterator_traits<std::vector<int>::iterator>::iterator_category());
IterT がテンプレート引数なせいでそこに typename をつける必要が出てくるわけだが
そこはC++の仕様だから適当に調べてくれ
説明はめんどい
>>543 それ、イテレータタグといってイテレータの種類がわかる
iterator_category()によってそのイテレータの種類を表す空の構造体を返してる
その空構造体で関数をオーバーロードしてる
たとえばdistanceとかでランダムアクセス可能なのにいちいち辿っていくのは効率悪いでしょ
なるほど、すごいテクニックだ。
こんな時間に初心者な質問してすまないんだが…
ぐぐってもドキュメント見てもわからなかったんで
助言頂けると非常に助かります。
VC++2008ExpressEditionを使用しているので、どこかを変更しなければいけないのか…
質問の内容は…
猫でもわかるプログラミングSDK第123章
ttp://www.kumei.ne.jp/c_lang/sdk2/sdk_123.htm これと同じプログラムを組んでも、WndProc内でcase IDM_READの
hMapFile2 = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "Kumei's Object");
のOpenFileMappingがNULLを返してくるんだけど
原因がまったくわかりませんorz
>548 環境依存だから、叩かれる前にVCスレ行った方が良いよ。
やっぱ環境依存なんですか… 教えてくれてサンクス VCスレで聞いてくることにします
551 :
543 :2009/03/06(金) 08:18:57
つまり関数のパラメーターを受け取る変数は省略可能ってこと? それってC++の仕様?Cでも可能?
>>537 >>539 >>540 そうですC++Builder2009の付属品です
boostのかなりの部分にも対応しましたし昔に比べればだいぶ
良くなったと思います(昔に比べればね。VCに比べれば糞だけど)
>>551 釣りか本気なのかわからんが…
distance(Iter, Iter)を例であげると実装は、distance内部で
return _distance2_(iter1, iter2, iterator_tag)
みたいなのが呼び出されて最適な関数がオーバーロードで呼び出されてる
使っている分にはiterator_tagを意識する必要はなく、distance(Iter1, Iter2)で呼び出せば良い
省略可能か、と言われると省略可能だな
本来iterator_tagはいらないんだろうけど、オーバーロードに失敗するコンパイラとかもあるから
こういう仕様になっている
554 :
517 :2009/03/06(金) 14:35:08
std::wstring wstr; wstr=L"sample"; std::cout << "test1\t" << ((std::wstring(L"sample")==wstr)?"true":"false") << std::endl; std::cout << "test2\t" << ((std::wstring(L"sample")!=wstr)?"true":"false") << std::endl; wstr=L"あいうえお"; std::cout << "test3\t" << ((std::wstring(L"あいうえお")==wstr)?"true":"false") << std::endl; std::cout << "test4\t" << ((std::wstring(L"あいうえお")!=wstr)?"true":"false") << std::endl; これで正しくは test1 true test2 false test3 true test4 false となるはずがBCC 5.5.1では test1 true test2 false test3 false test4 true となってしまうことについて聞いた者だけど、 その後いろいろいじってみたら次のことが分かった。
555 :
517 :2009/03/06(金) 14:36:12
>>554 続き
@〜が半角文字なら
std::wstring(L"〜")==wstr
も
wstr==std::wstring(L"〜")
も正しく動作する。
A〜が全角文字なら
std::wstring(L"〜")==wstr
は誤判定するが
wstr==std::wstring(L"〜")
は正しく動作する。
Bcompareメンバ関数は
std::wstring(L"〜").compare(wstr)
wstr.compare(std::wstring(L"〜"))
共に正しく動作する(等しい時に0を返す)。
…………………………
そこで、前に
bool operator==(const std::basic_string<wchar_t> &left_str,const std::basic_string<wchar_t> &right_str)
{return left_str.compare(right_str)?false:true;}
bool operator!=(const std::basic_string<wchar_t> &left_str,const std::basic_string<wchar_t> &right_str)
{return left_str.compare(right_str)?true:false;}
と記述してみたのだけれど、相変わらず
test1 true
test2 false
test3 false
test4 true
のままなのだ。これじゃだめなのだろうか?
556 :
デフォルトの名無しさん :2009/03/06(金) 14:40:15
>>553 釣りではない。
質問は単純で
void func(int){printf("int\n")};
void func(float){printf("float\n");}
というのがC++では可能なのか?ということ。
また関数名を変えて多態でなくすればCでも可能なのか?と尋ねてる。
引数を受け取る変数は必ず必要だと思い込んでいたので。
(iterator_tagに関してはあまり興味はない。)
>>556 Effective C++読むより先に入門書読め
>>555 BCC は全然知らないけど、UTF-8で書くと幸せになれるかもしれない
561 :
デフォルトの名無しさん :2009/03/06(金) 15:10:19
562 :
517 :2009/03/06(金) 15:20:18
>>559 UTF-8に文字コード変換してみたけど
幸せになりきれなかった。
いろいろとコンパイルエラーになる。
〜.cpp 32: 文字列または文字定数が閉じていない(関数 main() )
〜.cpp 33: ステートメントにセミコロン(;)がない(関数 main() )
〜.cpp 33: 文字列または文字定数が閉じていない(関数 main() )
〜.cpp 34: 文字列または文字定数が閉じていない(関数 main() )
*** 4 errors in Compile ***
う〜む。
Aのstd::wstring(L"〜")==wstrが誤判定でwstr==std::wstring(L"〜")は正しく動作する
のが不可解でならないんだよねぇ。
bcc5.5.1のこの不具合に対して誰か手を打った例を示した人(やソース)はどっかに公開されてないのだろうか?
1+2; とかけるんだから int hoge ( int ){ /**/ } のようなものも可能だな。 引数を受け取って単に捨てる。
前者と後者のつながりが良く分からない
565 :
デフォルトの名無しさん :2009/03/06(金) 17:49:09
566 :
デフォルトの名無しさん :2009/03/06(金) 17:50:59
>>561 個々のコンパイラでできるかどうかではなく、C++あるいはCの規格にあるのかを知りたい。
567 :
デフォルトの名無しさん :2009/03/06(金) 17:54:36
>>558 入門書では
引数をとる関数の定義には必ず引数を受ける変数が書かれているよ。
関数の引数を受け取る受ける変数を省略している例が書いてある入門書ってある?
あるなら教えて。
C++を少しでも知っていれば556みたいな質問しないだろう なぜ入門書すら読まずにここで聞くのか
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) {} でやってる時、「nCmdShowは使用されていません」みたいな警告が出て、 そこで変数名を消すと、警告が消える、みたいなことを味わうWin開発者。
570 :
デフォルトの名無しさん :2009/03/06(金) 17:58:25
572 :
デフォルトの名無しさん :2009/03/06(金) 18:02:59
>>568 あ、君の疑問がわかったよね。
>>556 はfuncが2つあることを疑問に思っているのではないよ。確かにそれならC++の入門書に書いてある。
でも疑問はそうじゃなくて
funcの引数が型だけで変数が無いことを疑問に思っているのだよ。
573 :
デフォルトの名無しさん :2009/03/06(金) 18:34:12
>>566 だったら規格票くらい買えよ
仮にここで「保証されてる」と答えても嘘かも知れないだろ
574 :
517 :2009/03/06(金) 18:43:14
なんか分かってきた。 BCC 5.5.1で bool operator==(const std::basic_string<wchar_t> &left_str,const std::basic_string<wchar_t> &right_str) {std::wcout << left_str << L"\t" << right_str << L"\t";return left_str.compare(right_str)?false:true;} と定義してみた。 std::wstring wstr=L"piyoあいうえお"; この時 std::wstring(L"piyoあいうえお")==wstr とすると左オペランドleft_strが「piyo」に、右オペランドright_strが「piyoあいうえお」になっている事が分かる。これが誤動作の原因だ。 wstr==std::wstring(L"piyoあいうえお") としたときは正しく左オペランド、右オペランド共に「piyoあいうえお」になる。 …さーて、BCC 5.5.1は見限るしか しようがないのかな。 どうにかして(つぎはぎ的にで良いから)動作させたかったのだが。
556の人は後置operator++の引数とかにいちいちしょうもない名前付けてるのかな
>>569 それよりもhPrevInstanceを省略するほうが先だろう。
>>574 よくわからんが<string>のバグ?を自分で修正すれば良いだけじゃね?
>>577 いや、他人の環境でも通用させたいライブラリ的な用途のつもりだから、
手元の修正じゃだめなんだ。
…ライブラリって言っても本気で公開したりとか言うつもりことはないんだけど、
経験のためにたまたま出会ったbcc5.5.1の不具合に対する対処を考えているところなのだ。
おせっかいかもしれないけどどうせ5.5.1じゃテンプレート周りもアレなんだから見限ったほうがいいよ
556は何をキレているのだ。 トム・デマルコがグルは口が悪いし意地悪だから 辛抱強く質問しろといってたじゃないかw で、結論から言うと、それはできる。 無名のオブジェクトで所有権の移譲が行われなければ それは単に捨てられる。パラメータに変数がない場合、 値渡しにせよ、参照にせよ、ポインタにせよ、 メモリのどこかにそれらが作られた後、単純に捨て去られる。 もちろん、オーバーロードは正常に機能する。
581 :
517 :2009/03/06(金) 19:32:10
>>579 やっぱそうだよねー
このスレの
>>376 もテンプレート周りがクソな事を示しているし。
一応bccの時のみコンパイル時に警告を表示させたいと思っているのだが
「bccの時のみ」は
#if defined(__BORLANDC__)
〜
#endif
で出来るがbccの
# pragma
で警告だせる?指定したメッセージの。
>>581 Turbo C++ Explorer 使っとけ。
この辺はまともになっている。
583 :
517 :2009/03/06(金) 19:58:07
>>582 どうもありがとう。
エラーメッセージは
#pragma message "気をつけてね〜"
でいいな。文面は適当に直すとして。
2年前にC++を学び始めた者です。 プロになるわけでもなく(別の職業があるので)単に趣味なのですが、 そろそろまた勉強になるC++の本を買いたいと思って探しております。 何か良い本はありませんか? Effective C++という本が人気が高そうだと思っているのですがどうでしょうか。
586 :
584 :2009/03/06(金) 21:20:31
訳に問題があるなら英語で読めば?
>>586 名著だが邦訳は糞。
原著で読めるならそれの方がいい。
>>566 C99+TC3では6.9.1でidentifierがなくてはいけないとなってます
590 :
デフォルトの名無しさん :2009/03/06(金) 21:49:43
訳本をボロカス言う者は2種類いる ・それを全否定しうる誤訳・悪訳を挙げられる人(正誤表が作れる) ・洋書を自慢したいだけなナンチャッテおじさん(ソースが2ch)
591 :
デフォルトの名無しさん :2009/03/06(金) 21:51:32
>>580 別にキレてないよ。どうしてそう思ったの?
それはともかくありがとう。
省略可能なのね。
592 :
デフォルトの名無しさん :2009/03/06(金) 21:53:47
>>573 それを言ったらこのスレの存在意義がないでしょ。
593 :
デフォルトの名無しさん :2009/03/06(金) 21:58:55
>>592 存在意義?
少なくとも「確認」に使う価値なんざねえぜ
所詮、便所の落書きだ
594 :
584 :2009/03/06(金) 22:01:20
>>587 >>588 私は英語にそこまで問題はないつもりですが、肝心のC++の知識の程度を加味しますと
結局「私のC++の知識で脳内で翻訳する原著」と、「C++の知識がある方が翻訳した訳本」とでは果たしてどちらがいいものでしょうか。
…と言ったことも加味して考えてみます。
ありがとうございました。
595 :
584 :2009/03/06(金) 22:02:14
>>590 先程アンカし忘れました。
ありがとうございました。
596 :
デフォルトの名無しさん :2009/03/06(金) 22:04:00
>>589 関数定義ではそうなのか。
プロトタイプ宣言ではどう?
定義では
void foo(int hoge){〜〜
になっていてもヘッダーで
void foo(int);
って書く人もいるじゃん。これはどう?
>>590 >それを全否定しうる誤訳・悪訳を挙げられる人(正誤表が作れる)
つまり、原書を読み、日本語訳も読んだってことだよな
原書を読んでいるのに、何でわざわざ日本語訳を購入して読むんだ
599 :
デフォルトの名無しさん :2009/03/06(金) 22:11:41
600 :
デフォルトの名無しさん :2009/03/06(金) 22:13:04
>>589 読み飛ばしてた。ゴメン。
つまり、C99では関数定義の引数の変数(識別子?)を省略出来ないってこと?
601 :
デフォルトの名無しさん :2009/03/06(金) 22:19:02
STL listでstringを追加していき、listから削除したらstringのメモリは解放されますか。 str.swap(string())のような開放しないといけませんか?
602 :
デフォルトの名無しさん :2009/03/06(金) 22:25:59
自己解決しました。 listの削除で開放しました。 list<string> L; string tmp(5*1024*1024,'a'); for(int n=0;n<1000;n++){ L.push_back(tmp);L.pop_back(); }
>>589 そんなバカな
それじゃvoid foo(void)は定義できないじゃないか
605 :
デフォルトの名無しさん :2009/03/06(金) 22:44:37
voidって型名なの? void a; って宣言できないよね。
ということにしたいんですね。
607 :
デフォルトの名無しさん :2009/03/06(金) 22:59:34
>>605 void a();
なら宣言できるけど、
型でなければ何だと思っていたわけ?
>>598 自分の場合は
・検索がしやすい
・読むときに辞書がいらない(移動中でも読める)
・他人と話をあわせやすい
なんかの理由で買ってる
効率考えたら日本語の方が良いしね
More Effective C++のようなゴミだとそうもいかないが
vector の配列って作れますか? vectorのvectorを作れば良いのかな?
作ろうと思えば作れるよ、vectorの配列 全くもってお勧めしないけどな
611 :
デフォルトの名無しさん :2009/03/06(金) 23:12:02
> ・検索がしやすい え??
まとめ。 C99 では(プロトタイプ)宣言では識別子は省略可能、関数定義では識別子が必要(void の場合を除く)。 > 9899:1999 > 6.7.5.3/6 > A parameter type list specifies the types of, and may declare identifiers for, > the parameters of the function. > > 6.9.1/5 > If the declarator includes a parameter type list, the declaration of > each parameter shall include an identifier, except for the special case > of a parameter list consisting of a single parameter of type void, > in which case there shall not be an identifier. No declaration list > shall follow. C++ では識別子は省略可能。 > 14882:2003 8.3.5/8 > An identifier can optionally be provided as a parameter name; if present > in a function definition (8.4), it names a parameter (sometimes called > “formal argument”). [Note: in particular, parameter names are also > optional in function definitions and names used for a parameter in > different declarations and the definition of a function need not be > the same. If a parameter name is present in a function declaration that > is not a definition, it cannot be used outside of the > parameter-declaration-clause since it goes out of scope at the end of > the function declarator (3.3). ]
>>611 たぶん「他人と話を合わせやすい」と似たような理由なんじゃないかな
日本語での表現を知りたいって理由もあるしね
もっとも、そこにそう書いてあるからってそれが一般的な表現とも限らないけどね
例えばJISの「返却値」とか
614 :
デフォルトの名無しさん :2009/03/07(土) 00:10:15
随伴とかなw
615 :
551 :2009/03/07(土) 00:22:03
>>612 わかりやすい。ありがとう。
C++では関数定義でパラメータの識別子を省略できて、
Cでは省略できないんだね。
617 :
551 :2009/03/07(土) 01:05:05
>>610 そうなんですか。
変数の個数のメンバーがあってそれに対応するvectorを作ろうとすると
vectorの配列が必要となるのですが、お勧めしないのであれば
どのような実装にすればいいか教えて下さい。
>>618 そういう時は、要求されるデータ構造を提示してしまうのがいいと思うよ。
vectorのvectorでよさそうな気がするけど。
vector<vector<?> > やっぱり、これですよね
vector<vector<?>> って書けないのが悔しい
nが関数fooの中で変更されない仕様になっていることが確実なとき、 void foo(int n) よりも void foo(const int &n) のが望ましいよね?後者は前者の完全上位互換だと思って良いかな?
>>622 いや、効率は悪化する可能性がある
すくなくとも前者より後者がよなる可能性はない
参照はポインタによって実装されているから後者は遅くなる可能性がある
>>623 初めて知りました。
クラスだったら話は別かな?
>>624 クラスでも、メンバ変数がint一個だったりしたら効率を落とす可能性はある。
>>625 なるほど。
std::stringぐらいだとどうかな?さすがに処理が重いか。
>>620 vectorのコピーが発生しまくりになるんじゃないかな
std::list<std::vector<?>>とかstd::vector<boost::shared_ptr<std::vector<?>>>のほうが軽くなるんじゃないかな
nが関数fooの中で変更されない仕様になっていることが確実なとき、 コンパイラ的には void foo(int n) よりも void foo(const int n) のが最適化しやすいから望ましいよね? 今度は後者は前者の完全上位互換だと思って良いかな?
プロトタイプ宣言につけず、 定義部分にだけconstつけるんならべつにいいんじゃね、ってなんかの本に書いてたで
そこにconst付けても何の意味もないだろう 最適化にも全く関係しないような
グローバルでもstaticでもない変数にconstつけても最適化には全く影響しないだろう
>>632 その代わりといってはなんだが、エラーチェックだけはしてくれるようになるぞ。
例えばそのfoo()で++nとするとエラーになるわけだ。
634 :
632 :2009/03/07(土) 14:08:50
>>633 変更するつもりが無いオブジェクトに付けておくと便利ってことね。
class hoge{ std::string test void setTest(char *str); void setTest2(std::string str); }; 便宜上setTestとsetTest2と名前を変えましたがオーバーロードとして残しておくか悩んでいるんですが どちらかを削るか残しておくかどちらのほうがいいんでしょうか?
setTest2(std::string str); って大変なことになるんじゃね? stringのインスタンスって、48バイトくらいあったような。 詳しい人説明よろしく。
高々48バイトだ、キニスンナ 4.8Mバイトなら、ちょっとだけ気になるがな
>>635 void setTest(const char *str);
void setTest2(const std::string& str);
setTestを削れば、setTest2は一時オブジェクトを作ってsetTestの代わりをすることも可能だね
testに値を代入するなら同じ名前でオーバーロードしておいた方が良い ま、それにしてもstringの方はconst string& strにした方が良いよ
641 :
622 :2009/03/07(土) 17:02:13
>>641 おそらく640は、int も int一個のクラスもコストは同じといいたいんだろう。実際VC++2005は同じコードが出ているね。
intやint一個のクラスで参照渡しだと間接参照になるのでオブジェクトをアクセスするときに余計なコストがかかるようになる。
測定して速いほうが正しい だいたいは、オブジェクトサイズが16バイトをこえたりする辺りが境界になるようだ ソースは俺の寝言
オブジェクトを複製するコストと、オブジェクトを間接参照するコストの比較で値渡しと参照渡しを選択する。
すごいあほなこと聞いてる気がするんですが void chkStr(char *hoge); void chkStr(char &hoge); って何が違うんでしょう?
上がアドレスを渡していて下が実体を渡してる 指している物は一緒
なるほど、ようするに*の場合はクラスであれば->を。 &の場合は.でいいってことですね、ありがとうございました
適当だな。納得してるならいいが
fgetsする時に第一引数がchar*になっていますがstring型を使うことはできないんでしょうか?
>>647 そしてクラスの場合[ ]の意味も変わってしまう。
string::c_str()使えば?
c_str()ってstringの内容をcharの文字列として出すもので入れるものじゃなくね?
ああ、そうかC++のstring型なのにcのファイル取得を使うからだめなのか・・・ filestream使えばいけるのかな?というわけで試してきます
ん。仕様では書き込みも保存も禁止だからやっちゃらめ。
stringへ読み込ませるならifstream+std::getline(グローバル関数のほう)だろう。
streamはゴミ
>>624 遅レスだが、暗黙にコンストラクタが呼ばれる可能性があるので、そのコストにもよる。
660 :
624 :2009/03/09(月) 13:25:54
int i=42; double d; この時 d=i;//@ d=static_cast<double>(i);//A この@の方は単純に代入しているだけで、Aはわざわざキャストであることをはっきり書いてるわけだが、その程度の認識しか俺はしていない。 Aで書く意義はあるの?
書かなくていいよ。 そういう安全なキャストをいちいち明示するのは可読性を下げるだけ。
>>662 俺もそう思っているのだが、みんなはどう考えているのか是非聞きたい。
static_castはテンプレート用だす。
>>665 boost::numeric_castは便利そうだな。
どうやって実装してるんだろうね。
オーバーフローの可能性がある組み合わせだけ特殊化してチェック処理入れるんだろ
669 :
661 :2009/03/09(月) 23:59:21
あと、 d=i;//@ d=static_cast<double>(i);//A この2つで実行時のコードの速さは理論的には差はないんだよね? 例えクラスAとB(Aを継承)で A a; B b; a=b;//@ a=static_cast<A>(b);//A だったとしても、同じだよねぇ?
std::string hoge="I am hoge."; std::cout << hoge+"test" << std::endl; std::cout << hoge+="test" << std::endl;//問題の行 こうすると、 問題の行: このコンテキストではオーバーロード 'endl' が曖昧(関数 main() )
673 :
672 :2009/03/10(火) 00:05:25
>>672 っていわれるんだが、どのへんが曖昧なのか分かる??
+=の優先順位が低いんじゃないの? (hoge+="test")としてみるとか
>>672 std::cout << ( hoge+="test" ) << std::endl;//問題の行
あと、cout の中で演算をしてはいけない。
かぶった。あと、「してはいけない」じゃなくて「しないほうがいい」にしておいて^^オマンコ
677 :
672 :2009/03/10(火) 00:16:48
なるほど。 ()付ければいけるな。 あとcoutの中で演算しない方が良いのは何で?
たとえば以下のようなコードを実行するとわかる。 int i = 0; cout << ++i << ++i << ++i << ++i << ++i << endl; 予想される結果は「12345」だけど、実際にはめちゃくちゃになる。 << の評価順は規定されていない。どこから評価されるか不明。 ステートメントの終わりに i が 5 になるのは確かだけど。
679 :
672 :2009/03/10(火) 00:24:37
>>678 俺の環境では54321になった。
なるほど、そんなんあったなぁ。
foo()==bar()
でどっちが先に評価されるか未定義なのと同じかい?
ここで颯爽とインクリメント不要論が登場
>>678 それは未定義。隣接する副作用完了点の間で、同じオブジェクトを二度以上変化させてはならない。
683 :
672 :2009/03/10(火) 00:39:08
cout << ++i << endl; だとどうなる? これは未定義の動作になる?それとも不定?
>>683 評価される順序は:
(1) cout, ++i, endl
(2) 左側の<<
(3) 右側の<<
(1)の3式の順序は不定。
>>675 も同様。
685 :
682 :2009/03/10(火) 00:46:31
厳密にはオブジェクトではなく、スカラオブジェクトだったか。
686 :
672 :2009/03/10(火) 00:52:01
>>684 んんん???
なんかクソ難しいな。
int i=-1;
で
if(++i){〜}
は良いんだよね?
(++i)+(++i)
はダメなの?
++iが意味不明に思えてきた。
俺のドタマで理解できる日は来るのだろうか?
わかっててヤル分にはいいんじゃないかな a += (++i)++; とか
>>686 ごく簡単に言うと、一文の中で変数を書き換えられるのは高々一回。
int i;
j = i++; // OK
j = i++ + i++; // NG
689 :
687 :2009/03/10(火) 01:11:42
>>686 いや俺 分かってない
>>688 >ごく簡単に言うと、一文の中で変数を書き換えられるのは高々一回。
むっちゃくちゃ分かりやすいな。
みんなから習ったことを俺なりの言葉で述べてみると、
int i=-1;において、
@if(++i){〜}は良い。
動作は、iがインクリメントされてその値が式の値となりifでの評価に使われる。
A(++i)+(++i)はダメ。
なぜなら、+の前後のどちらが先に評価されるかは不定であり、また(++i)という副作用が生じる式が一つの式の中で2回行われているというところは未定義の動作になる。
Bstd::cout << ++i << ++i << ++i << ++i << ++i << std::endl;もダメ。
なぜなら、<<の前後のどちらが先に評価されるかは不定であり、また++iという副作用が生じる式が一つの式の中で5回行われているというところは未定義の動作になる。
Cstd::cout << ++i << std::endl;は良い。
動作は、まずstd::coutと++iとstd::endlの3者が順不同で評価される(順番に関しては不定な動作)。
しかし副作用が生じる式が++iの1つしか含まれていないため未定義にはならない。その後std::cout << ++iが評価され、「std::cout << ++iの戻値」と << std::endl;とで評価が行われる。
690 :
デフォルトの名無しさん :2009/03/10(火) 01:15:57
それは「副作用」とは言わない。
691 :
687 :2009/03/10(火) 01:19:05
>>690 ある式を評価したら何らかの変数やオブジェクトの値が変わる場合、その式は副作用を生じると称する。
…んだと思っているんだが、間違い?
692 :
デフォルトの名無しさん :2009/03/10(火) 01:39:33
正解
693 :
687 :2009/03/10(火) 01:48:06
ええと、違う変数なら良いんだよね? つまりn=(++i)*(++j)は正しいんでしょ? 一方 n=(++i)*(i)はダメだよね?*の前後の評価順序に関して不定。さらに++iとiがある点が未定義になるんだよね? …なんとなくつかめてきた感がある。 要は、 「++iってインクリメントしたらその文中でiを他に参照しているところがあってはならない」 って言う風にまとめられるのかな。
とりあえず評価順に依存するプログラムは書かない方が良いよ
695 :
デフォルトの名無しさん :2009/03/10(火) 01:51:55
手続き型言語全否定
>>693 >つまりn=(++i)*(++j)は正しいんでしょ?
そのとおり。かまわない。
>一方 n=(++i)*(i)はダメだよね?
そのとおり。
697 :
687 :2009/03/10(火) 02:01:42
>>696 ありがとう。
なんとなくつかめてきたよ。
>>698 std::stringに限って言えばぶっちゃけインデックスだけで十分だと俺は思うんだが。
findがインデックスを返すし、それをイテレータに足すなんてやりたくない。
…コンテナとしてはイテレータが役立つけど。
>>698 一見するとconstでないメンバ関数(コンストラクタ含む)の時のみイテレータが実装されているみたいじゃね?
…何でだろうね。
STLが標準に取り入れられる前からstringはあったんじゃなかったっけ。 それの関係じゃないの。
誰も提案しなかったので採択もされませんでした…という話か。
あるいは他のSTLとの整合性とか。
704 :
デフォルトの名無しさん :2009/03/10(火) 19:10:53
おいらの彼女がC++ほどマーケティングに汚染されてないストイックな言語はない…濡れる・・って毎晩求めてくる。おいらは下からの侵入とかいって毎晩楽しんでるけどいいよね??
705 :
デフォルトの名無しさん :2009/03/10(火) 19:12:39
良いんじゃないのかなまぁ
setlocale(LC_ALL, "ja"); /* ロケールを日本語に設定 */ このLC_ALLって正式な標準C++仕様ですか?
>>706 そうだけど、"ja"はC++標準ではない。""ですむならそのほうがいいはず。
さらに言えば、C++ならstd::locale::global(std::locale(""))使うべき。
708 :
デフォルトの名無しさん :2009/03/10(火) 23:47:54
LC_ALLについて聞いてるのに、なんで"ja"について答えてるんだよ
709 :
706 :2009/03/10(火) 23:50:12
>>707 >>708 ありがとうございます。
std::locale::global(std::locale(""));
std::wcout.imbue(std::locale(""));
これが正解ですか?
Effective C++によれば、仮想デストラクタを持たないBaseクラスを継承させたDerivedクラスは危険であると言います。 その例としてSTLのコンテナが挙げられていました。 しかし例えば class MyStringClass : public std::string {〜} とし、MyStringClassのデストラクタとして特にすることが「全くない」場合、MyStringClassを今後継承することはないものとして、それでもなお危険なのでしょうか? std::string * p =new MyStringClass; delete p; とした場合はMyStringClassのデストラクタは呼ばれませんが、std::stringのデストラクタは絶対呼ばれますよね?
>>711 いや、未定義動作になるのでそうとは限らない。
713 :
デフォルトの名無しさん :2009/03/11(水) 08:49:54
コンテナは継承しないのが鉄則だろう 包含、非メンバ関数で処理するのは駄目なのかい?
未定義だったの? ポインタの型に合わせて呼ばれるだけなのかと思ってた
715 :
デフォルトの名無しさん :2009/03/11(水) 09:16:55
ポインタの型に合わせて呼ばれ、未定義の結果を生じる
ポインタの型std::stringに合わせて呼ばれ MyStringClassのデストラクタが呼ばれず未定義の結果を生じる。
>未定義の結果を生じる
719 :
711 :2009/03/11(水) 12:52:55
みなさんありがとうございます。 std::string * p =new MyStringClass; delete p;//1 この1では未定義の動作になるのですね。 では MyStringClass * q =new MyStringClass; delete q;//2 や MyStringClass x;//3 はどうでしょうか。1の使い方をしないで必ず2ないし3の使い方をするならばその限りにおいては未定義にはなりませんよね? …もっとも、他者に1の使い方を明確に禁じる方法はありませんけど。
720 :
711 :2009/03/11(水) 12:55:06
>包含、非メンバ関数で処理するのは駄目なのかい? 私の状況に限れば大丈夫なんですけれど、まあ言語仕様上の疑問でして。。。
>>719 1も2も3も何れも動作は定義されている。全て安全。
未定義とか言ってる奴はど素人だから信じなくていい。
>>721 いや1は未定義だろ。
std::string(=基底クラス)のデストラクタだけが呼ばれることが[多い]ってだけで、仕様上は未定義だろ?
*p->~string がどうやって「あ!オレMyStringClassだったわ」と気づくのかね?
724 :
デフォルトの名無しさん :2009/03/11(水) 13:17:28
三つとも未定義 沈黙のエラー、メモリリーク、メモリ破壊、ポーティングになる コンパイラもアロケータもエラーにしないだけ
基底クラスのデストラクタが呼ばれるのが未定義なら virtualにしてても呼ばれない可能性があるってことか?
726 :
724 :2009/03/11(水) 13:25:58
すまん よく見てなかった ポインタ、参照を使用してない三番は未定義じゃないわ
>>728 未定義だよ
5.3.5
if the static type of the operand is different from its dynamic type, the static type
shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
1は未定義 2、3は動作する でもコンテナとか継承を想定してないクラスを規定クラスにすんなハゲ が結論
>>725 deleteは静的な型を元にデストラクタを呼ぶ。
>>719 の1の例だと
実際の型はMyStringClassだけどdeleteに渡されるのはstd::string型なので
std::stringのデストラクタが呼ばれる。
しかしstd::stringのデストラクタは非仮想なので、
>>729 の通り未定義動作。
仮にstd::stringのデストラクタが仮想なら、実際の型MyStringClassのデストラクタが呼ばれ
正常に解体できる。
わかんねえならデストラクタは必ずvirtualにしろっての 大した考えなしに非virtualデストラクタを作るのはテポドンをでたらめに撃ちまくるのと同じだ
733 :
デフォルトの名無しさん :2009/03/11(水) 20:09:59
C++で参照(リファレンス)型の変数にポインタを代入する際に キャストは必要ないですか? たとえば Hoge *foo = new Hoge(); //1行目 Hoge &bar1 = *foo; //2 Hoge &bar2 = foo; //3 bar1.func(); //4 bar2.func(); //5 は正しい?
734 :
デフォルトの名無しさん :2009/03/11(水) 20:12:41
735 :
733 :2009/03/11(水) 20:15:23
2行目は正しくて3行目はおかしいということであってますか?
736 :
デフォルトの名無しさん :2009/03/11(水) 20:16:33
キャストがどうのって問題じゃない
737 :
733 :2009/03/11(水) 20:30:18
ああ、キャスト云々がおかしいのですね 最初の質問の「キャストは必要ないですか?」の部分は削除します その場合どうでしょうか?
738 :
デフォルトの名無しさん :2009/03/11(水) 20:41:23
739 :
デフォルトの名無しさん :2009/03/11(水) 20:45:05
>>735 コンパイル通るかどうかくらい実験しているんだろうな?
2行目は代入していないし、ポインタでもない
代入と初期化の意味が大きく異なる典型例
>>739 2行目は1行目の結果で初期化するだけだから何も問題ないだろ。
寧ろあんたこそ実験してみたら?
>>733 そういうわけで、2行目は大丈夫。必然的に、4行目も大丈夫。
但し、参照先の寿命に要注意。余りお勧めはできない。
741 :
711 :2009/03/11(水) 22:55:05
レスが遅れてすみません。 5.3.5のくだり if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. を訳すと もしオペランド(演算対象)の静的な型と動的な型が異なる場合、静的な型は「オペランドの動的な型の基底クラス」になる。 そしてその静的な型は仮想デストラクタを持つべきであり、さもなければ挙動は未定義である。 となります。 そして std::string * p =new MyStringClass; delete p;//1 この場合、 pの静的な型はstd::string* pの動的な型はMyStringClass* よって5.3.5のくだりにより未定義の動作になるのですね。ここは理解しました。 そして MyStringClass x;//3 が未定義でない事も明らかです。Non-copyable Mixinとかのイディオムがあるくらいですし。ここも理解しました。 では MyStringClass * q =new MyStringClass; delete q;//2 はどちらでしょうか? qの静的な型はMyStringClass* qの動的な型はMyStringClass* だとしますと問題無く動作することが仕様上保証されているのではないかと思うのですが。
742 :
739 :2009/03/11(水) 23:00:08
>>740 俺に振ってる理由がさっぱりわからん
気でも狂ったか?
>>741 何ら問題ない。
そうじゃないと非仮想デストラクタのクラスはnewできない事になってしまう。
元々ポインタで扱ってる変数を 参照に入れる意味が分からん
745 :
デフォルトの名無しさん :2009/03/11(水) 23:10:04
>>740 >>733 は初期化とは言っていない
寧ろあんたこそ初期化と代入を混同してるだろ
つーか、死ねば?
746 :
711 :2009/03/11(水) 23:10:20
>>744 俺の勝手な予想だが、「元々ポインタで扱ってる変数」を「引数として参照を取る関数」に渡す時とかじゃないか?
独立参照にする意味は分からんけどさ。
748 :
デフォルトの名無しさん :2009/03/11(水) 23:19:47
名前の付け替えくらい普通にやるだろ。
名前の付け替え....イクナイこと企んでいるな
VC++2008でいろいろ試してみた結果 初期化はできたけど代入は無理だった。 ロベールにも参照先の変更は_って書いてあるから_ってことでF/A?
>>750 typedef int(*neko)(int)
neko tama = &nyao;
neko pochi = &wan;
neko giko = &shine;
>>753 みたいなことは普通にやるけど、
>>733 の3が合法なのか。
そりゃ内部表現は同じだろうけど、2しか使ったことがないよ。
驚いたと言うより、気持ち悪いな。
>>754 そんなわけない。もちろん3番はコンパイルエラーだよ。
C++の標準仕様を学ぶための場所(英語可)を教えてくれ
>>759 いつも思うのだが、あれってどうにかしてダウンロードできないのかね?
不便で仕方ない。
キャッシュ使うなりパケットをキャプチャするなり何なりと…
ブラウザのpdfリーダープラグインを切れよ
763 :
762 :2009/03/12(木) 14:43:54
オーノー 保護されてるのか すまんかった
>>763 昔は761のような方法でダウンロードできた代わりに全ページ画像だった。
今でもそれを持っているけど、やっぱり手元に保持できるのは便利だと思う。
766 :
758 :2009/03/12(木) 15:19:58
演算式文字列を計算するクラスや関数ってどこかに落ちてませんか? "4 * (3 + 2) / 2" "1 + (1 <= -1 ? 100 : 200) * 2" のような文字列を数値にしたいのですが。
>>769 それぐらいの言語プロセッサ自分で設計しろ
>>769 その規模ならboost::spiritで割と簡単にできる。
std::string hoge="sample_string"; この時、hogeのインデックス3で表される部分から3文字分の文字を削除した文字列を出力したい時は hoge.erase(2,3); std::cout << hoge << std::endl; とすればよい。だがコレではhogeの内容が改変されてしまうし、何よりhogeがconstだったら通用しない。 そこで std::cout << std::string(hoge).erase(2,3) << std::endl; std::cout << hoge << std::endl; という代案を考えて見たのだが、このように 「テンポラリオブジェクトに対する破壊的なメンバ関数の呼び出し」 は問題無く動作することが仕様上保証されている?
773 :
772 :2009/03/12(木) 23:22:14
>>772 >hogeのインデックス3で表される部分から3文字分
じゃなくてhogeのインデックス2で表される部分から3文字分だったか。まあ主旨には関係ないけど。
>>772 大丈夫だったはず。
でなけりゃ std::vector<T>(v).swap(v); ができなくなってしまう。
775 :
デフォルトの名無しさん :2009/03/12(木) 23:47:35
/V\ | /◎;;;,;,,,,ヽ, | _ ム::::(,,゚д゚):| J ヽツ.(ノ:::::::::.:::::::.:..|) ヾソ:::::::::::::::::.:ノ ` ー U'"U'
>>774 その式の動作はわかるが目的がわからない
>>776 capacity()とsize()を一致させる為の常套手段
例外安全を確保するときにもつかうよね
std::vectorでcapacityを0にする、つまり確保したメモリを開放する方法は提供されていますか?
とりあえずそのスコープから脱出する
782 :
772 :2009/03/13(金) 00:26:09
やっぱ使うよね。 どうも!
記述の簡便さに比べCPU時間はエライ事に。
エライこととは定量的には?
C++の標準ライブラリでファイルストリームから 改行文字までの1行を取り出す関数なんかってありますかね?
>>786 すいません改行文字も取り込みたいのですがどうしたら可能ですか?
>>787 なんのために?
どうしてもと言うなら std::getline() の後に結果の string の
末尾に '\n' を付け足せば同じことだと思うんだけど。
見直せばそりゃ語りっぽいよなぁと思いつつ、質問は本当です
>>789 ファイルを読み込むとき末尾が改行で終わってるのか、改行なしで終わってるのか分からなくなるんです。
------ ビルド開始: プロジェクト: null, 構成: Debug Win32 ------ コンパイルしています... null.cpp c:\program files\microsoft visual studio 9.0\vc\include\math.h(29) : error C2059: 構文エラー : 'extern ' c:\program files\microsoft visual studio 9.0\vc\include\math.h(29) : error C2143: 構文エラー : ';' が '{' の前にありません。 c:\program files\microsoft visual studio 9.0\vc\include\math.h(29) : error C2447: '{' : 対応する関数ヘッダーがありません (旧形式の仮引数リスト?) c:\program files\microsoft visual studio 9.0\vc\include\math.h(488) : error C3861: 'fabs': 識別子が見つかりませんでした 同じようなC3861エラーいっぱいだから省略 c:\documents and settings\dareka\my documents\visual studio 2008\projects\null\null\null.cpp(206) : error C2668: 'sin' : オーバーロード関数の呼び出しを解決することができません。(新機能 ; ヘルプを参照) c:\program files\microsoft visual studio 9.0\vc\include\math.h(577): 'long double sin(long double)' の可能性があります。 c:\program files\microsoft visual studio 9.0\vc\include\math.h(529): または 'float sin(float)' 引数リスト '(double)' を一致させようとしているとき c:\documents and settings\dareka\my documents\visual studio 2008\projects\null\null\null.cpp(209) : error C2065: 'cout' : 定義されていない識別子です。 c:\documents and settings\dareka\my documents\visual studio 2008\projects\null\null\null.cpp(214) : error C2065: 'endl' : 定義されていない識別子です。 場所が違うだけの同じエラーいっぱいだから省略 null - エラー 58、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== そういえば上に書いたHP見ながら作ったHelloworldもusing namespaceがなくて困ったな・・・ もしかして情報ふるいのか?
>>792 VC2008だよね?
C++以外の言語がどのくらいの経験者か分からないけど、コンパイルエラーは最初のものを見るのが基本。
構文エラー : 'extern '
これが最初だから最も怪しい。
どうせ
'extern 〜で;が抜けてるとか?
標準ヘッダでエラーがでるのが変だな #inclue <math.h> の前の行に何か変な文字が入ってるとかないか? あるいは直前のヘッダにエラーがある(最後のセミコロンが抜けてる)とか
>>791 よくわからんが、ファイル名変えてみたら?
ソースコードをそのまま写してるのか自分で理解しながら書き直してるのかどっち?
みんな教えてくれるのに肝心なことを書かずにすまない。 VC++2008をつかってて、ソースはいちおう写し書き #include "stdafx.h" #include <iostream> using namespace #include <math.h> void main() { double deg,a, b; // a, bは三角形の2辺の長さ(m)。degはその間の角度(度) a = 1.6, b = 1.6, deg = 90; double rad; rad = deg * 3.1415927 / 180; // sin()の引数の単位はラジアンなので180度で割ってπを掛ける double s; s = a * b * sin(deg * 3.1415927 / 180;) / 2; // ここで面積を計算している。 cout << "2辺の長さが"; cout << a << "(m)と"; cout << b << "(m)で、" << endl; cout << "その間の角度が" << deg << "(度)の三角形の面積は"; cout << s << "(平方m)" << endl; } VC++入れなおせば直ったりするのかな・・・
VC2005で試したけど確かにmath.hでエラーはいてるw
799 :
デフォルトの名無しさん :2009/03/13(金) 13:31:18
3行目
using namespace std; にして s = a * b * sin(deg * 3.1415927 / 180;) / 2 この行180の後にセミコロンになってる 名前空間指定してるんだけどどの名前空間使うか指定してないっていう;
おぉ、すんなりと出来てしまった。 エラーログだけじゃなくて、ソースも出さないと駄目なんだな・・・ みんなありがとう、嬉しくてニヤニヤしたよ。 これからバイトだけど、帰ってきたらusing namespaceについて調べてみる。 ちなみに、引数と関数ってどういう意味なんだろうか。 >引数(ひきすう)とは関数に与える値のことです。当然ですが引数の数は関数によって違います。関数は実行されると値を返します。この値を戻り値といい、関数が示す値になります。例えば > > double y; > y = log(1.0); > >と書いた場合、1.0が引数で、yに戻り値(多分0だろう。)が代入されます。 791のアドレスに上の説明がされてるけどさっぱり・・・ 引数と関数はどういう奴なのか詳しく解説してるところはない?
>>801 つーか、初心者スレを覗いてみたらどうだ? もっとましな入門サイトを教えてくれるかもしれないぞ。
804 :
793 :2009/03/13(金) 14:20:39
>>801 >ちなみに、引数と関数ってどういう意味なんだろうか。
>#include <math.h>
この質問から察するに、C++以外の言語の経験もあまり無いのか?
サイトを見るより書籍を買う方がオススメだよ。
安い書籍でも中古でもいいから入門書を買って来て通読した方が良いかと。
805 :
793 :2009/03/13(金) 14:22:58
806 :
793 :2009/03/13(金) 14:30:08
>>803 数学の関数とプログラミングの関数は、似ている様で全く意味が違うだろ。
数学では変数の値は絶対に変わることはない。
x=1な世界でしばらくしてx=2になっていることはない。
同様に関数は写像であり、それ以上でもそれ以下でもない。
環境っていう隠された引数があると考えれば関数と見なせないこともない
値が変わらないものは変数といいません。定数といいます。
いいえ束縛です
違うものだとしても数学の関数を知っていればCの関数も想像し易いだろ。 全く別のものに同じ名前はつけないからね。 同じ名前である以上なんらかの共通点がある。
あの頃のアタイとは違うんだよ!
>>812 定積分でもxの値は変わってないよ。
高校数学でx=aからbまで変わっている「かのように」思えるのは、仕方なしにそう説明しているだけで。
(歴史的経緯もあるし、変わっているように考えた方が分かりやすいんだろうがね。)
リーマン積分でもルベーグ積分でもそれ以外の気持ち悪い積分でも変わっているわけではない。
じゃ「変数種類 x を動かす」以外の実装方法ってあるの?
また明後日の方向に逸れる…
816 :
813 :2009/03/13(金) 18:04:05
>>814 数学に実装なんて用語はない(定義や公理のことかい?)。
変数種類 x なんて用語は数学にもプログラミングにもない。
…まあいいよ、知りたきゃルベーグ積分でググれ。それか数学スレいって質問すればよか。
俺は単に引数と関数が中学の数学の教科書に書いてあるって言った
>>803 に反対したまでで、これ以上汚す気になれない。
>>802 初心者スレって★初心者にVisual C++を教えるスレ★ Part33で合ってるかな?
そこを覗いたら猫でも分かるプログラミングってサイトが紹介されてた。
ちょっくら漁ってみるよ。ありがとう。
>>806 親切にどうもありがとう。
Wikipediaの奴は、引数を見る前に関数を見たら少し分かった気がするよ。
『引数 意味』で調べたときに仮引数と実引数が出てきて困ったけど
ちょっと理解できたから良かった。
書籍はもう少ししてから買ってみるよ。
黒い画面とにらめっこしなくなるくらいまでは、その辺のサイトで覚えたいと思ってる。
とりあえず、みんなありがとう。
>>816 変数の値が変わらないなんてマヌケなこと言ってるのは、関数型言語を最近触りだけ覚えたど素人だろ?
数学的にもプログラミング的にも頭悪すぎる。
知ったかぶる前にちゃんと勉強しろ。
しょせん数学にしろ算数にしろ正しいであろうって実装して枠組み決めていっただけだから実装ってあるんじゃね? 1+1は1+1であるっていう定義とともに+は足し算である。って実装があるって考え方も・・・定義ともいえるが
変数は、決まらないから、変数っていうんですよ
数学にはメモリがないから「変わる」という表現はおかしいな 数学の(自由)変数というのは定義域内のどの値でもよいという存在 特定の値を持っていてそれが動くというより、ある範囲そのものというイメージの方が合ってる
822 :
デフォルトの名無しさん :2009/03/13(金) 23:44:03
範囲は集合、変数は元。 変数が範囲そのものというイメージは捨てた方がいい。明らかに間違い。
イメージの話だってば 変数は元だけど、変数である限りはどの元でもいいんだから、 変数を使って何かを表現したときはその定義域全体に対しての表現になるわけだろ その意味では範囲と思って間違いじゃないと思うんだけど
824 :
813 :2009/03/14(土) 00:08:58
>>818 >>変数の値が変わらないなんてマヌケなこと言ってるのは、関数型言語を最近触りだけ覚えたど素人だろ?
なんか激しい誤解をしている様だが、とりあえず、この話題を頭から一語一句もう一度読んでくれ。
C/C+の変数は確かに内容が変わりうる。俺の書き込みの中でそれに反対した場所は1箇所もないよ。
>>819 >>1 +1は1+1であるっていう定義とともに+は足し算である。って実装があるって考え方も・・・定義ともいえるが
「公理系」の事を言いたいのかな?。
例えば、かの選択公理を容認する公理系(ZFC)と認めない公理系とか、有名どころではユークリッドの平行線の公理を認める公理系と認めない公理系とか。
その意味では確かにプログラミングの実装に似ているとも言えるな。
>>820 方程式2x=aでもxが変数でaが定数という言い方をするとおり、x=a/2が同値。決まる。
要は変数xとは「着目している」数ないし数に類する集合の元ってことだな。
いい加減スレ違いうざいよ
826 :
デフォルトの名無しさん :2009/03/14(土) 00:53:59
>>824 帰れ。ど素人。
>>806 がお前の書き込みかどうかは知らんが、
>>806 は
「数学では変数の値は絶対に変わることはない。」
と言ってる大バカ者。この下らん議論はそこから始まってる。
少なくとも
>>806 はバカ。以上。
>>826 だからスレ違いは子ねってつってんだろ!
顔を真っ赤にしてそんなに書きこんでんじゃねぇよ
829 :
デフォルトの名無しさん :2009/03/14(土) 01:47:56
ファイルの末尾の話なの?行末の話だと思ってた。
はあああ?
函数?
C++を全世界で禁止するために有効な方法を 教えてください。
コンピューターを破壊せよ
834 :
デフォルトの名無しさん :2009/03/14(土) 10:47:34
C++の本を大量に購入してから、25人殺して、捕まって、 取り調べで「俺はデストラクタになりたかった」って言えばいいよ。
あと、テンプレート殺人とかですね
危険思想を多重継承していくと良い。
梁にロープひっかけてダングリングポインタ。
>>834-837 クソフイタw
つい…かっとなって…gotoしてしまった。
…気がついたら… 怖くなって逃げました。
馬名二文字で延々代を重ねていくと結構シュール
C++でstd::cinのdelimiterを追加・変更したいんですが、どうすればいいですか? Javaでいうjava.util.Scanner.useDelimiter(**)みたいな使い方ってできない?
thisって付けられる箇所はすべてにthisをつけるべきなんでしょうか。面倒区サインですが
842 :
デフォルトの名無しさん :2009/03/15(日) 19:13:55
つけなくていい
thisはりよう禁止
いや、this は必要だろw
引数名とクラスメンバ名が被ったときだけthisをつけるでOK?
そもそも被らせないようにすべき
c++だと初期化リストを使いたいときに、 Foo() : _bar(bar) {} こうしてしまう。
アンダースコアを識別子の先頭に書くのは(ry メンバ変数はグローバルスコープではないけど、 あるバージョンの処理系から急にキーワードとして使われた場合に問題になる
>>848 先頭アンダースコアのメンバ変数ならその心配は無いよ。
まぎらわしいから使うべきじゃないのは確かなんだけどね。
別にbar(bar)でも問題ない…ないと思う。間違ってたらスマネ 俺は public constなデータメンバは先頭大文字、 privateなデータメンバは末尾にアンダースコア、 引数とかは先頭小文字で末尾アンダースコアなし って決めてるからかぶることはないけどね
>>849 だから _bar というキーワードが追加された時に
コンパイルが通らなくなると言っとるに
>>850 > 別にbar(bar)でも問題ない
試してみた、うわあああ!!!!
俺はこの数年間なにをしていたんだ!!!
ずーっともやもやしながらアンダースコアつけてたw
>>851 _bar は処理系独自のキーワードには使えないよ。 __bar ならアリだけど。
例えば、Visual C++の場合、__stdcallとか__asmのような下線付きの独自のキーワードは、 拡張ありだと_hoge/__hoge(下線1つと2つ)の両方を認識するが、 拡張なしだと下線2つの__hogeのしか認識しないようにきちんとなっている。
bar(bar)ダメ HP-Unixじゃ受け付けないから禁止
使っていい識別子のルールはややこしいから - 頭にアンダースコアは一律禁止 - 2個連続したアンダースコアは一律禁止 としてしまうのが安直で簡単だとおもう
>>856 んなかたわの環境なんかどうでもいいよ。あれもこれも中途半端な実装なんだから。
bar_とかやってたら別にm_barでも悪くないって気がしてくる 接頭辞ってオムニ補完使うときに便利なんだよね
m_ g_ 何も悪くない。
int_p_ MyClass_pp_
>>855 拡張ありでダメならダメだってことだろう・・・
>>853 メンバ変数に印付いてないと
どれがメンバ変数なのか分かり辛いし
ローカル変数名とうっかり被ったりすることもあるので
結局メンバ変数には何らかの印を付けた方がいい。
メンバ変数に何の印も無いソース読んだ事あるけど、かなり悲惨だった。
一人で管理するなら何が何なのか把握してるんだろうけどさぁ・・・。
bar(bar) を利用するのは簡単な構造体のみにしてくれ。
>>862 規格を逸脱したコンパイラベンダの独自拡張なんか気にしてたら何も安心して書けないぜ。
極端な話、 MS が将来の言語拡張で a を独自のキーワードにしない保証はあるのかい?
>>865 _bar なら心配だけど bar なら安心だと思うんでしょ?根拠もなしに。
867 :
デフォルトの名無しさん :2009/03/15(日) 23:52:36
_T はあったな
868 :
デフォルトの名無しさん :2009/03/15(日) 23:53:14
>>865 保証はあるのかという問いへの答えになってないぞ
>>867 アンダースコアに続いて英大文字なら規格の許す範囲内。
コンパイラ拡張もnamespaceで括るの必須にして 古いソースは use namespace で逃げるようにしようや
new VeryLargeClass[BIGNUM] という式は、ヒープに確保しきれなかった場合など、問題が生じればstd::bad_alloc例外が投げられるんだよね? mallocならNULLが返される。 …では、そうではなくて VeryLargeClass vlc[BIGNUM]; の様に宣言した結果、コールスタックに確保しきれなかった場合などは何が起こるの?
どのコンパイラでもみんな#pragma microsft::visual_cpp::onceですね わざと混合させてみた。
>>871 まあ現実的には、シグナルが飛んだり (Unix系) とか独自の例外が投げられたり (Win)とか。
基本的に、そうなることはC++例外が投げられるより想定外の事態だね。
874 :
871 :2009/03/16(月) 00:31:18
>>873 ほほう、すなわちそんな事は滅多に起こらないと考えて良いの?
…それとも起こらないように過度にでかい領域はnewでヒープに確保するように気を配るべき?
スタックにしろヒープにしろ、領域溢れるようなサイズを取らないよう プログラム時に考慮するのは当然
すいません。以下のコードはなぜ正しく動きませんか。 #include <stdio.h> class Test { private: int value; public: Test(void); void getValue(int*); }; Test::Test(void) { value = 10; } void Test::getValue(int* value) { value = &(this->value); } int main(void) { Test test; int* value; test.getValue(value); printf("%d\n", *value); }
>>867 はローカルスコープで
「_+小文字」は使用が許されているが 「_+大文字」は不可なことを示す良い例だね
ためになる
「_+小文字」でメンバ変数名を定義するぞ!
>>877 やめといたほうがいいぞ。
それやってると >848,851 みたいな人と無用な議論をする破目になる。
>>876 説明するのも面倒だから、こうすりゃ動くってのだけ書いておく。
void Test::getValue(int* value)
{
*value = this->value;
}
int main(void)
{
Test test;
int value;
test.getValue(&value);
printf("%d\n", value);
}
>>878 C++は、一人で完結する実験や趣味プログラムでしか使わないからOK
>>879 なんで
>>876 のプログラムじゃダメなんすか。Cの考え方では問題ないですよね。C++特有の問題なんでしょうか。
Cでもだめだ。同じこと。
void Test::getValue(int** value) { *value = &(this->value); } int main(void) { Test test; int* value; test.getValue(&value); printf("%d\n", *value); }
ああ、コピーした情報を書き換えてるだけだからダメなのか。ポインタって難しい。。
885 :
デフォルトの名無しさん :2009/03/16(月) 02:08:35
仮想関数の使用方法について質問です。 class Base { public: virtual void foo()=0; } class Derived1 : public Base { int x; public: void foo(); } class Derived2 : public Base { int x; int y; public: void bar(): } //関数の実装やらは省略します int main() { Base *pBase = new Derived2; pBase->bar();//としたい } Baseにbarの純粋仮想関数を追加しても当然ながらDerived1に影響がでます。 この場合どうすればよいのでしょうか?そもそも純粋仮想関数を使うべきではないのでしょうか? ご教示下さい。
886 :
885 :2009/03/16(月) 02:13:11
すみません、Derived2のメンバ関数に void foo(); が抜けてました。
「Derived1に影響がでます」ってことは、Derived1はbarなんて操作は知らない/要らないってことかな。 そうだとしたら、BaseとDerived2の間に純粋仮想関数barを持つ抽象クラスを挟むとか、継承関係を見直した方がいいんじゃない。
888 :
885 :2009/03/16(月) 02:32:16
「間に挟む」ですか!そういう手があるのですね。 大変参考になりました。ありがとうございました。
継承関係をいじりたくないなら、何もしないbarをBaseに書くしか無いかな。
でゅあるひえらるきー
Base* 使うなら889の仮想関数が正解だと思うが
Base::barでassertか例外投げとくといいかもね。
893 :
885 :2009/03/16(月) 02:50:05
VC使ってるんですが、pBase-> と打った時点で(´・ω・`)なりました。
そうですね、
>>889 さんの方法でやってみたいと思います。
894 :
デフォルトの名無しさん :2009/03/16(月) 04:57:44
初心者ですがこのプログラムは動くのでしょうか? あるHPに掲載されていたものなのですが動かないので疑問に思いました 【多分間違い】 #include <stdio.h> int main(void) { printf("Hello, world"); return 0; } 【たぶん正解】 #include <stdio.h> int main (void) { printf("Hello World\n"); return 0; }
全角空白を使っている分、後者をエラーにするコンパイラのほうが多いはず。
>>894 "\n"の有無の問題ではない事は確か。
エラーの内容を書いてみたら良いと思うよ。
>>885 のpBase->bar()部に至るまでにBase*がDerived2である事の判断をしてるだろうから
分岐直後にポインタキャストすればいいんじゃないかな
>>881 折角C++なんだからポインタ使わず参照にしろよ。
# って書くとポインタ原理主義者が怒りそうな気はするw
>>881 >なんで
>>876 のプログラムじゃダメなんすか。Cの考え方では問題ないですよね。C++特有の問題なんでしょうか。
C言語で書かれているようにしか見えないが、まあともかくどっちでもダメだよ。
試してみれば分かる。そもそもコンパイラでコンパイル時に変数が未使用だとのwarningが出るのでは?
もう解決しているみたいだけど一応言っておくと、
void Test::getValue(int* value)
{
value = &(this->value);
}
これは「int型へのポインタ」型の変数valueがコピー渡しされている。
コピー渡しである以上、ローカル(=getValue内でスコープ限定)なポインタvalueの値がどれだけ変わろうと、
呼び出し元(main関数)から見れば何も起こっていないも同然。
…まあミスを誘発した原因の1つとして、仮引数と実引数で同じ名前を使っていることじゃない?
900 :
871 :2009/03/16(月) 13:48:17
901 :
デフォルトの名無しさん :2009/03/16(月) 15:05:26
explicitを使わないことで起りうる問題って具体的にどんなことがありますか?
>>901 勝手に型変換されるのが嫌な場合じゃない?
例えば
int型を受け取るMyClassのコンストラクタMyClass::MyClass(int num)があったとして、
void foo(MyClass hoge);
という関数に間違ってfoo(42)と記述しちゃった場合にも暗黙に
foo(MyClass(42))
とキャストされるからコンパイルエラーにならない。
>>902 それが出来ることがどうしてダメなのか、もっともらしい理由が知りたいんです。
ただ、そういう書き方も出来るというだけじゃ、全然問題にならないじゃないですか
問題にならない、じゃなくて、問題に感じられないの間違いでした。正確には
こういうのに違和感があるとか、 std::vector<std::string> v = 5; //vは5個の要素を持つと指定 まずいことが起こる可能性を少しでも排除するためとか。 void f(std::auto_ptr<int> const& p, int x); int g(); f(new int, g()); 引数並びの評価順序は決まっていないので、 例えばnew int→gの呼出→auto_ptr<int>の構築→fの呼出という順番だったとき、 gの中で例外を投げられるとnewした分が漏れてしまう。 これを少しでも防ぐためにも、explicitが使われている。スマートポインタは変数で構築しろと。 まあ、それでもf(std::auto_ptr<int>(new int), g());と書けばコンパイラは通してしまうのだけど。
906 :
902 :2009/03/16(月) 16:03:16
>>905 >それが出来ることがどうしてダメなのか
>問題に感じられない
別にダメじゃないよ。むしろそっちの方が分かりやすいこともある。std::string(const char *)とかはexplicitじゃないしね。
ただ前後関係というか文脈上(見た目上)コンストラクタで勝手にキャストされるととても気持ち悪い事がありえるので、
その気持ち悪い状況の時にexplicitをつける。
具体的には…
…と思ったが
>>905 が書いてくれているらしいな。
前にDirect3Dのスレで出ていたが、こんな例もある。 float4つのベクトルを表すD3DXVECTOR4という型があるんだが、 これはfloat*を返すoperator float*()という関数と、 float*を引数に取るexplicitでないコンストラクタがある。 機能は推して知るべし。 んで、この型では、次のような式がエラーにならない。 D3DXVECTOR4 v; v = v + 1; // ベクトルにスカラーを足しているのにエラーにならない! 何でこんなことになったかというと、まずD3DXVECTOR4には、当然intとのoperator+()は定義されていないから、 コンパイラは暗黙の型変換を探す。 そこで見つかるのがoperator float*()。 ポインタと整数の加算は合法だから、右辺はfloat*型のポインタになる。 んで、次に代入の部分が評価される。 D3DXVECTOR4にはfloat*を引数に取るoperator=()はないから、やっぱり別の暗黙変換を探しに行くんだけど、 ここでたまたまfloat*を引数に取るexplicitでないコンストラクタがあるもんだから、 右辺がD3DXVECTOR4に変換されてしまう。 結果的に上記の式は、メモリのアクセスエラーを発生させてしまうことになる(しかも検知しにくいたちの悪いエラー)。 要するに、explicitなしのコンストラクタと暗黙の型変換を行うoperatorは、併用すると思わぬところで危険な動作を引き起こすってことだ。
>>907 うわー。ネタかと思って試してみたら、ホントだった。
警告レベルを最高(W4)にしても、VC++2008で警告出さずにコンパイルできちゃう。
DirectXの設計ミスじゃないのか。これ。
せめて、DXD3DXVECTOR4(const float *begin, const float *end)くらいに
できなかったのかなあ。標準ライブラリとも整合性ないし。
909 :
デフォルトの名無しさん :2009/03/16(月) 23:34:49
おまえらときたら…
気がついたらもう900代か。消化はやいな。
テンプレート関数を使うときに、const 参照と普通の参照の両方を使う場合は どうするのが効率良いでしょうか? template<typename A0, typename A1, typename A2> void f( A0& a0, A1& a1, A2& a2); template<typename A0, typename A1, typename A2> void f(const A0& a0, A1& a1, A2& a2); template<typename A0, typename A1, typename A2> void f( A0& a0, const A1& a1, A2& a2); template<typename A0, typename A1, typename A2> void f(const A0& a0, const A1& a1, A2& a2); …… とかboost::preprocessorでやっていたら組合せ爆発で死にました…… 引数の総当たりなんてやるもんじゃないなぁ。
効率云々以前に、constにできるものはすべてconstにする。
913 :
911 :2009/03/17(火) 01:39:11
>912 ライブラリ(Visitor)なのでconst & と & の両方構える必要があります。 決め打ちだと簡単だけど、利便性が格段に落ちるからなぁ……
その手のものはスクリプトで自動で吐き出すのが流行だったんじゃないの?
template<const A,~const A[1]>f(const A a0~ , const A [1]); template<A,~A[1]>f(A a0~ , A [1]); template<A,~>f(A a0,~){typeof(a0) xx[1] x; f(a0,a1,a2,x)}
916 :
911 :2009/03/17(火) 02:51:31
>914 boostぐらいしか使用しないポータブルなライブラリを作っているので、 まずはboost::preprocessorでチャレンジしました。 >915 それは何でしょう?コンパイル失敗しましたが……
これって0xなら全部&&にしておけば問題ないパターンだよね?
0xは流行しないから禁止
>>917 &&って何?
&&hogeみたいに使う新しい演算子が出るの?
>>919 rvalue referenceでぐぐれ
921 :
911 :2009/03/17(火) 20:41:14
>917 いや、ダメですね。委譲する関数次第では左辺値参照で扱う必要があるので、 右辺値参照決め打ちにすることは出来ません。 const&と&を自動で切り替えるテンプレートがあればいいのですが……
>>921 やりたいことはbindとかfunctionのようにほかへ引数を渡すような感じだよね?
それなら、perfect fowarding問題として知られていて、
右辺値参照で解決を期待されている事柄の1つ。
詳しくはstd::forwardでググるといいと思う。
923 :
911 :2009/03/17(火) 22:52:05
>922 そうです。perfect fowarding問題かぁ。 とりあえず8変数までは何とか回っているので、しばらくはこれで凌ぐことにします。 それ以上の変数が必要になったらテンプレートクラス使って明示指定することにしよう……
どうでもいいが ×テンプレート関数 ○関数テンプレート ×テンプレートクラス ○クラステンプレート
>>924 関数テンプレートを具体的に指定して出来た関数がテンプレート関数で、
クラステンプレートを具体的に指定して出来たクラスがテンプレートクラスだっけ?
926 :
911 :2009/03/18(水) 00:59:42
>924 あれ?そうだったっけ……ということで標準を見てみたけど、確かにtemplate function / classという 用例はほとんど無いね。 non-template〜〜ばっかだった。
>テンプレートを具体的に指定して出来た 単に関数、クラスでいいと思う。 型を与えたテンプレートは、型を明記した同様の関数/クラスと同じ振る舞いをするから、区別する必要は無い。 テンプレートを具体化(instantiate)した事を強調したければ、具体化関数/具体化クラスと呼べるのかな。あんまりしっくりこないけど。
928 :
911 :2009/03/18(水) 01:03:30
>925 ちなみに標準だと Template instantiation instantiated function instantiated class ね。
テンプラの良書ってありますか?
930 :
927 :2009/03/18(水) 01:05:52
おっと、標準がそうなら日本語でも具体化関数/具体化クラスとした方がいいかな。
今まで散々インスタンスのことを「実体」と呼んできてるんだから instantiatedは「具体化」ではなく「実体化」が素直だろ。
そのインスタンスはクラス(型)に対する実体を意味しているのであって、 テンプレートに対してパラメータを与えることとは意味が違わない?
違わない。同じ。
void foo(const std::string &str){}; という関数があった時に、 foo("hoge"); と呼び出したらどうなりますか? コンパイル時に何の警告もでないのですが、 「std::stringのconst char*が受け取れるコンストラクタ」でキャストされているのですか?
935 :
934 :2009/03/18(水) 17:02:20
追記: void foo(std::string str){} の場合はキャストされますよね? void foo(std::string &str){} としたら未定義の動作になっちゃったりとかしますか?
キャストではない、暗黙の型変換
>>936 3コードとも試してあります。
bccはvoid foo(std::string &str){}で勝手に一時変数を作りました。
g++はコンパイルエラーになりました。
その他の2コードは特に何も問題無いようです。
>>937 暗黙の型変換ですか。
明示的な型変換はキャストと同義ですか?
最近のコンパイラ(有名どころのGCCとか)は、相当最適化機能が優秀だから 下手にinlineとか付けないでもうコンパイラの最適化まかせにしちゃっても大差ないと 聞いた。 みんなはどう考える?ぜひ意見を聞きたい。
下手もへったくれも、inlineは書く必要がない。
メンバ関数の実装をヘッダに書くか、それともcppに書くかはプログラマが決めなきゃならないのでは? ヘッダに書いたメンバ関数(クラス定義の外)は、inlineが必要なんだよね?
この前もどっかで書いたばかりの気がするけど、 自分は、最適化なんて意識せず、 returnだけの1行とかmin/max並に単純なものなど、 ヘッダに書きたければinlineを付けるという基準でやっている。
1) ヘッダでは一切、メンバ関数の定義をしない 2) ヘッダには一切、余計なincludeをしない な奴は俺と友達。
945 :
デフォルトの名無しさん :2009/03/18(水) 18:40:36
>>944 リンケージ的になにもなしじゃまずいだろう
宣言がクラス内にあるのだから、何の問題もない希ガス。
>>941 >ヘッダに書いたメンバ関数(クラス定義の外)
そんなことしたら、他のファイルでそのヘッダをインクルードしたら定義が重複してるぜっていうエラーがでないか?
>>945 なるほど、あのふざけた重複スレをPart67に仕立て上げたのか。
だからinlineを
>>950 ああinlineすれば大丈夫になるのか。意味不明なレスしてすまんかった。
参照を返すメソッドがあって、その戻り値が有効かどうかを判定したいのですが NULLと比較するとコンパイルエラーになります。 どうすればよいのでしょうか?
例外を投げる
>>952 参照は有効な物の参照しかとらないようにコーディングすべき。
無効なポインタと同じで、無効な参照は検出不可能。
ちなみにNULLはポインタだからコンパイルエラーになる。
ちなみに無効なものの参照ってどうやって返すの?自動変数の参照とか?
mapコンテナを返す、しかしmapのキーが今まで登録した事ない場合です
957 :
954 :2009/03/19(木) 01:18:04
>>955 そっちのが難しいよな(笑)
俺としてはnewして得たオブジェクトをdeleteしちゃった後のことを想定している。
なんか話が全然かみ合ってないなぁ。
説明が悪かったでしょうか classでも構造体でも、intでも何でも良いのでキーにしたmapコンテナを作り そのclassなり構造体の参照を返すコードを、キー指定のmapコンテナを記述です。
960 :
954 :2009/03/19(木) 01:33:57
その説明でより状況が悪化した。 反復子を返したいのかね
>>960 うん。
エスパーするとmapを包含したクラスがあって、map::findの結果を参照で返すメソッドがあるのかな。
そうだとしたら、参照は無効な状態を表すことができないので、無効である(見つからなかった)ことを表現するなら例外を投げるしか無い。
戻り値がポインタならNULLを返すという手はある。
map::findで得られた反復子の有効性を判断したいのであれば、map::end()と比較して、同じなら無効。
こんな感じです。 struct AB { int a; int b; }; std::map< int, AB > global; void SetVal( int key, int a, int b ) { global[ key ].a = a; global[ key ].b = b; } AB& GetVal( int key ) { return global[ key ]; } こんなソースの場合です。
>>963 global[key] と書くと、
- key に等しいキーを持つエントリがない場合はそのエントリを作成した上で、
- そのエントリの値への参照を返す
という動作をする。
したがって、そのコードは無効な参照を返さない。
解説ありがとうございます。 と言うと、つまりエラーチェックは出来ない訳ですね? 未初期化の実体が返ってくると、、 訳あって、その処理コードは使うだけで手を入れる事が不可なんです… あー、コード直したい
ひどいね。 globalが本当にglobalならexternで無理矢理参照してしまうとか(冗談です)
もう対抗するには、こちらもスマートさを捨てる事にします。 登録関数をラッパーして、キーをベクターコンテナに登録 取得関数をラッパーして、キーを検索、見つかったら本当の取得関数コール で行きます… 諸兄の皆様方は、何か良い案は有りますでしょうか? 条件は、ヘッダーインクルードだけで使うのみ、です。
>965 operator[]は値が無い場合はデフォルトコンストラクタで初期化する。 無いことを確認したいのならばmap::findを使うべきですな。 >訳あって、その処理コードは使うだけで手を入れる事が不可なんです… グローバル変数使っているようなコードに依存するのもなんだけど、自分のところだけは アダプタ使ってアクセスするようにしたら? やっつけコード template<typename AB> struct Adapter { static std::map<int, AB> global() { return global; }; void value(int key, int a, int b) { std::map<int, AB>& m(global()); m[key].a = a; m[key].b = b; }; AB& value(int key) { std::map<int, AB>& m(global()); std::map<int, AB>::iterator i(m.find(key)); if (i == m.end()) throw "Error"; return *i; }; };
ごめんなさい、追加の条件で使うだけの人間は、私を含めて複数います。 (だからチェック機能が欲しいのです)
>>969 ありがとうございます。
ただ、globalとは、例に出すのに私が付けた変数名なだけでして…
ようは、ソースは見れるのですがヘッダーと***.aなのです。
ああ、globalの実体には触れないのね。 >968 をするなら std::setの方が良いよ。
>>972 こちらも、ありがとうございます。
重複キーの場合どうするか皆と話して、かつ実際の使用されるキーの個数も視野にいれ
検討対象とさせて頂きます。
そのライブラリ、ソースは見れても、再コンパイルはさせて貰えないの?
はい、お仕事の都合上、デバッグの為にソースもらっただけなので… 最初は中できとんと処理されてると思ったのですが、共同が変になる場合があり ソースもらって見た瞬間に理解したんですが… 作った側曰く、少しでも速度を稼ぐため、エラーチェック無し、正しく使うのが前提との事です。 (実際の取得メソッドはインライン関数です)
大変そうだけどがんばってね。 しかし、少しでも速度を稼ごうとする奴がこんなコード書くかなぁ。 global[ key ].a = a; global[ key ].b = b;
>>975 コードの見た目で処理が減ってるように見えるだけで、速度を稼ぐことにはなって無いよ。
内部的には find() の戻り値をチェックするのと同等の分岐が必要になる。
>>968 その方法で良さそうというか、常套手段。
あるいは、mapに登録するクラスのデフォルトコンストラクタに無効フラグを設定するか。
その上で、元のクラスを変更するよう訴え続けるべし。
>>963 ふと思ったんだけどさ、GetVal というメソッドを、CreateValと改名すれば
なんか許せる気分になるな。ほらファクトリーもどきでw
・・・だめだ自分をごまかせねぇ OTZ
>>968 単に元コードが変更できないだけで、ラップしてそのメソッド利用を強制できる環境なら、
GetValの代わりに、getValを作るとか、GlobalMapクラスを作成して、
globalをprivateメンバにして、利用はGlobalMapのメソッドからアクセスするように
すりゃいいんじゃないのか。
キーをベクタに登録するよりはましな感じが。globalに直接アクセスしているライブラリが
でーんとあるとかいうなら、また別な話だが。
part67 はテンプレ付きで立て直したほうがいいと思うんだが、どうか?
くだらん事で増やすな その次にしろ
今のところからテンプレ追加すりゃ良いよ。
>979 問題は「既にキーが存在するかどうかが判らないクソ仕様になっている」つうことですな。 ラップするだけじゃ情報が足りないのね。
992 :
デフォルトの名無しさん :2009/03/20(金) 14:25:35
埋めめめ
999 :
デフォルトの名無しさん :2009/03/20(金) 14:29:53
1000 :
デフォルトの名無しさん :2009/03/20(金) 14:30:43
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。