■過去ログ置き場に戻る■ 1- 前250 次250 最新50


[memo] "9999999999_00.html#R20" という感じで、URLの最後に "#RレスNo" を追加すると幸せになれます。

C++相談室 part28
751 名前:デフォルトの名無しさん :04/03/29 17:34
768 名前: 762 [sage] 投稿日: 04/03/26 00:18
勉強のためゆくゆくはAbstractFactoryとかPrototypeパターンを使用するつもりなので。

#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr<A*> APtr;

class B {
public:
B() {
a.insert(APtr(new A("aaa")));
a.insert(APtr(new A("bbb")));
}
~B(){}
private:
std::vector<APtr> a;
};

でコンストラクタ呼ばれました。便利ですね。

追加質問ですが、自分で、deleteするのが面倒ならば、
常に、new をshared_ptrで包んだ方がいいですか?何か弊害ありますか?

769 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 00:20
>>766

それはまあ、実際のコードではAは抽象クラスで...
みたいになっているのではないかな。

752 名前:デフォルトの名無しさん :04/03/29 17:35
770 名前: 762 [sage] 投稿日: 04/03/26 00:42
デストラクタですた。失礼。
それと、a.push_backです。これまた失礼しました。

771 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 00:45
>>768
そうですね。shared_ptrで包まずに書けばメモリリークします。
772 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 00:47
> 追加質問ですが、自分で、deleteするのが面倒ならば、
> 常に、new をshared_ptrで包んだ方がいいですか?何か弊害ありますか?

むしろ、
shared_ptr を使うなら
・自分で delete してはいけない。
・常に new を shared_ptr で包まなければいけない。
さらに、 shared_ptr のテンポラリオブジェクトは作らないほうがいい。

753 名前:デフォルトの名無しさん :04/03/29 17:35
773 名前: 753 [sage] 投稿日: 04/03/26 08:29

結局、以下のようなものを作りました。やれやれ。
template< typename CharT > struct todigit_impl
{
 static inline int cvt( ChatT ch, std::locale const & lc )
 {
  CharT a[] = { ch, '\0' };
  std::locale old = std::locale::global( lc );
  int i = atoi( a );
  std::locale::global( old );
  return i;
};

// wchar_t 版を特殊化
...

template< typename CharT >
inline int todigit( CharT ch, std::locale const & lc )
{
 return todigit_impl< CharT >::cvt( ch, lc );
}

774 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 15:36
標準Cライブラリにも 「数字1文字」→「数値」ってなかったけか?なんか以外だ。
775 名前: 774 [sage] 投稿日: 04/03/26 15:37
×以外 → ○意外

754 名前:デフォルトの名無しさん :04/03/29 17:36
776 名前: Help me please! 投稿日: 04/03/26 16:56
どなたかお助けください。
以下の様に動いているプログラムで、sub()の中で再度ファイルを
オープン・クローズしてますが、それをやらないで例えばoutを引数として
渡して、実際にはプログラムのいろいろな所からよく呼び出されるsub()
を実行したいと思っているのですが、out を引数としてプロトタイプの
中で宣言するとエラーが起こってしまいます。なにかよい方法はあります
でしょうか。

よろしくお願いします。

#include <stdio.h>
#include <fstream.h>

void sub()
{
ofstream out;
out.open("log.txt", ios::app);
out << "sub executed" << endl;
out.close();
}

void main()
{
ofstream out;
out.open("log.txt", ios::app);
out << "log started" << endl;
sub();
out.close();
}

755 名前:ここまでしか持ってない :04/03/29 17:37
777 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 16:58
void sub(ostream &out);

778 名前: デフォルトの名無しさん [sage] 投稿日: 04/03/26 17:13
古いヘッダ使うな

779 名前: Help me please! [sage] 投稿日: 04/03/26 17:19
777さん ありがとうございます。それでうまく行きました。
ofstream は渡せないかと思って、voidにキャストしたりして
わけがわからなくなっておりました。レファレンスすれば
よかったのですね。

756 名前:デフォルトの名無しさん :04/03/29 18:09
>>755
亀レスになるがポインタでもええよ。要するにofstreamオブジェクト
をローカル変数と見なして(というか実際ローカル変数)、そのスコー
プが外れないように注意すればよい。

757 名前:デフォルトの名無しさん :04/03/29 21:49
VC++7.1付属STLやSTLPortのstringは
参照カウンタ方式じゃないようです。
g++3.2.2では参照カウンタ方式の様です。
パフォーマンス的にどうなんでしょう。
スレッド安全とか言い出すとコピーした方が
早いって事でしょうか?

758 名前:デフォルトの名無しさん :04/03/29 22:38
boost::shared_ptrも参照カウント方式だけどスレッドセーフ。
あまり関係なさそう。
copy-on-writeはC++では当たり前のように使われる最適化手法
だな。

759 名前:auto_ptrの質問 :04/03/30 11:20
std::auto_ptr() に operator!() や operator T*() が無いのは何故でしょうか。
暗黙の変換による予期せぬ動作を避けるためですか?

生ポインタを使った既存コードを、例外フリーにするため auto_ptr に変更中ですが、
p => p.get() の書き換えが大量に必要になるため、以下のラッパークラスで処理する
ことを考えています。
template<class T> class my_auto_ptr : public std::auto_ptr<T> {
public:
explicit my_auto_ptr(T* p = 0) : std::auto_ptr<T>(p) {}
bool operator!() const { return get() == NULL; }
operator T*() const { return get(); }
};
これで問題が起こるケースは、my_auto_ptr<T> p(...); delete p; にて二重デリート、
が思いつきますが、他にありますでしょうか。

760 名前:デフォルトの名無しさん :04/03/30 13:35
>>759
>これで問題が起こるケースは、my_auto_ptr<T> p(...); delete p; にて二重デリート、

operator deleteをprivateにしてみては?

>他にありますでしょうか

printf("%d", p);

printf("%d", (T*)p);
としないとmy_auto_ptrのインスタンスが渡されますね。

761 名前:デフォルトの名無しさん :04/03/30 13:50
ModernC++Designの7.スマートポインタでそこら辺を触れているので
一読をお勧めします。個人的には、関数にポインタを渡すときにgetと
releaseの二つが可能なのであって、勝手にgetを呼び出してしまうのは
危険なような気がします。まあ、関数にreleaseして渡すぐらいなら
auto_ptr引数にするって発想もあるんだろうけど。

書き換えの手間って言ってもコンパイルエラーを直すだけでは?
それ以前に"auto_ptrを使う=newを利用する"なんでしょうけど
そんなにnewを使いまくるってのもいかがなものかと。


762 名前:auto_ptrの質問 :04/03/30 18:49
>>760-761
ありがとうございました。printf() の場合には気付いていませんでした。
operator delete()をprivateにするのは良いアイデアですね。

新たに書き起こすならば、素直にauto_ptrを使い、get/release を使いますが、
今回は、既存のコードの変更行数を少なくする(ただし安全を満たす範囲内で)が重要なのです。
たしかにコンパイルエラーの箇所を get() 利用に直すだけで済むのですが、変更行数が多いと
工程管理上、派生する問題が大きくなるので避けたいという、政治的な動機です。
手動で書き換えても、暗黙変換させても、どちらにしても実際のバイナリコード変化量は変わら
ないというのは承知しています。

763 名前:デフォルトの名無しさん :04/03/31 09:59
>>758
勝手に話に割り込みますが、何を持ってスレッドセーフとなるのでしょうか。
shared_ptrを見てもロックをかけてるようには見えないのですが。

マルチプロセッサなんかでカウントの増加と減少が同時に起こったりはしないのですか?

764 名前:デフォルトの名無しさん :04/03/31 10:17
>>763
> shared_ptrを見てもロックをかけてるようには見えないのですが。
boost/detail/shared_count.hpp を BOOST_HAS_THREADS で検索しる。

765 名前:デフォルトの名無しさん :04/03/31 17:34
本当に初歩的な質問で恐縮なのですが,,。

当方、VC++6でダイアログベースのプログラムを組んでいて
ある特定のキーが押されたかを判定したいのですが,
ダイアログにコントロールを乗せるとキーが押されたというメッセージがうまく届かないらしいのです。

何かいい解決方法はないでしょうか。,

766 名前:デフォルトの名無しさん :04/03/31 17:41
スレ違いです

767 名前:デフォルトの名無しさん :04/03/31 18:03
>765
わたしはVC++など買える身分でないので、お答えできません。
相応しい人がいるスレに移動してください。

768 名前:デフォルトの名無しさん :04/03/31 18:43
スレ違いには誘導してあげるのが正しいスレ住人のあり方だろうとは思うけど
それを人に強制するのもなんなので俺が誘導。

>>765
あなたが質問すべきスレはこちらですね。

★初心者にVisual C++を教えるスレ★ Part11
http://pc5.2ch.net/test/read.cgi/tech/1077965179/

それとついでに、そちらに書き込むときはもっと具体的に書きましょう。
なにキーを押してなんというメッセージがどこからどこに届くはずだったのに
どうなった、ぐらいは書かないと答えようがありませんよ。

769 名前:デフォルトの名無しさん :04/03/31 20:22
>>764
あ、、、
こういうことやらなきゃいけないだろうとは思っていたけど、
これだと汎用性無くなっちゃいますよね。
そんなマイナーな環境を使うことが無い自分には知ったこっちゃ無い話ではあるけど。

こういう排他制御の標準も決めるべきだよなぁ。

770 名前:デフォルトの名無しさん :04/04/01 00:53
765です。

完全にすれ違いだったようですね
お騒がせしました。

771 名前:デフォルトの名無しさん :04/04/01 01:01
ファイル出入力が失敗したときに詳細を報告するため、以下のようなコードを思いつきました。
try
{
 errno = 0;
 std::ofstream output( ... );
 output.exceptions( std::ios::badbit | std::ios::failbit );
 ...
 output.close();
}
catch( std::exceptions const& e )
{
 throw std::runtime_error( ( errno != 0 ) ? std::strerror( errno ) : e.what() );
}

そこで質問なんですけど、C++例外処理とerrnoの親和性ってどうなんでしょうか?
とりあえず、ファイルが開けなかったりする単純なケースでは上手く動いてくれているみたいです。
上のようなコードでとんちんかんなエラーを報告してしまわないか、少し心配です。

772 名前:デフォルトの名無しさん :04/04/01 01:20
>>771
C++の標準ライブラリはerrnoに一切関知しない。だから
Cのstdio.hと同等な結果を得ようとするならばerrnoは自前で
セットする必要がある。それは例外が投げられた後である。

逆にCのライブラリを呼んでerrnoがセットされたら、該当する
C++の例外を投げるように設計する。

773 名前:auto_ptrの質問 :04/04/02 16:33
>>760
> operator deleteをprivateにしてみては?

やってみたら、期待した効果がありませんでした。
my_auto_ptr<T> p;
delete p; // no error
delete &p; // error by private operator my_auto_ptr<T>::delete().
前者に対して、errorになることを期待したのですが、甘かった。

774 名前:デフォルトの名無しさん :04/04/03 13:40
 C++ を学習し始めたが、本によって書き方(言語仕様)が違ったり、コンパイラを変えるとコンパイルエラー
を起こしたりするな。
 本によって、#include <iostream.h> の .h や using namespace std; があったりなかったりするな。
 コンパイラによっては、.h がないとインクルードできなかったり、using namespace std; があると
std の識別子が認識できずエラーになったり、string のオブジェクトを使うとエラーになって、試しに
#include の .h を取り除くと通ったりとか、cout の書式整形用の識別子を認識できずエラーになったり
してめちゃくちゃやのお。

 正しい C++ を学習するには正しい本と正しいコンパイラを選ばなければならないか。

775 名前:デフォルトの名無しさん :04/04/03 13:45
いつ頃のstandardや実装に基づいて書かれたものかを意識しないと
dでもない目にあうと思う。特にC++は。


776 名前:デフォルトの名無しさん :04/04/03 13:47
>>774
本はまずはプログラミング言語C++第3版。
<iostream.h>は古い規格(1989年以前)の書き方だね。

コンパイラは、たとえばVisual C++ 6.0はその1989以前のもの。
Visual C++ 7.1は現行規格対応。

777 名前:デフォルトの名無しさん :04/04/03 13:49
>>776
VC6はそこまでは古くもない気もするが、というか
1989じゃなくて1999かな。

778 名前:777 :04/04/03 13:50
>>777
1998だった。

779 名前:デフォルトの名無しさん :04/04/04 00:30
とりあえずさ、春休みの厨房・工房といえども、
まともにC++使えるようになりたいんなら、
入門書とEffective C++くらいは目に通しておこうや。

適当にサイトみてメチャクチャなプログラム書き出して、
2chで質問してるやつがここ数日多すぎるよ...。


780 名前:デフォルトの名無しさん :04/04/04 00:54
>>779
んな感じだな。

まじめに勉強する気があったら「プログラミング言語C++ 3rd」は手元においておけ。
値は張るがC++を学ぶ以上、必須だ。
大抵の疑問はこれ見れば解決するし。

781 名前:デフォルトの名無しさん :04/04/04 06:10
ポインタを格納するlistコンテナをポインタの値ではなく、ポインタの参照先の値でソートしたい場合はどのようにすればよいのでしょうか。
ポインタの配列にこだわっているのはポリモーフィズムを使用したいためです。

例えば以下の例ではCTestオブジェクトへのポインタの値でソートするのではなく、CTestのm_Numメンバの値でソートしたい場合どのようにすればよいのでしょう。

自分で調べたなかではgreaterがつかえそうなきがするのですが、greater自体を良く知らないもので....
やはりソート処理を独自に一から組むしかないのでしょうか、せっかくlist::sort()が用意されているのに自分で一から組むのはかっこ悪いし、どうかよろしくおねがいします。


782 名前:デフォルトの名無しさん :04/04/04 06:10
#include <iostream>
#include <list>
using namespace std;
class CTest
{
int m_Num;
public:
int GetNum() const { return m_Num; }
void SetNum( int Num ) { m_Num = Num; }
bool operator>( const CTest& obj ) { return m_Num > obj.GetNum(); }
bool operator<( const CTest& obj ) { return m_Num < obj.GetNum(); }
};
void main()
{
list< CTest* > l_pTests;
for ( int i = 0; i < 10; ++i )
{
CTest* pTest = new CTest;
pTest->SetNum(rand());
l_pTests.push_back(pTest);
}
l_pTests.sort(); // ポインタの値ではなく、m_Numの値でソート出来るようにしたい

list< CTest* >::iterator itCur, itEnd = l_pTests.end();
for ( itCur = l_pTests.begin(); itCur != itEnd; ++itCur )
{
cout << (*itCur) << ' ' << (*itCur)->GetNum() << endl;
delete (*itCur);
}
getchar();
}

783 名前:デフォルトの名無しさん :04/04/04 06:35
struct sorter {
 bool operator ()(const CTest *lhs, const CTest *rhs) const {
  return *lhs < *rhs;
 }
};

l_pTests.sort(sorter());

CTest::operator<()()をconstにしないと、このままじゃ通らないけどな。

784 名前:781 :04/04/04 06:41
すいません解決しました。

class CLapTest
{
public:
CTest*m_pTest;
bool operator>( const CLapTest& obj ) { return m_pTest->GetNum() > obj.m_pTest->GetNum(); }
bool operator<( const CLapTest& obj ) { return m_pTest->GetNum() < obj.m_pTest->GetNum(); }
};
void main()
{
list< CLapTest > l_LapTests;

for ( int i = 0; i < 10; ++i )
{
CLapTest LapTest;

LapTest.m_pTest = new CTest;
LapTest.m_pTest->SetNum(rand());
l_LapTests.push_back(LapTest);
}
l_LapTests.sort();
list< CLapTest >::iterator itCur, itEnd = l_LapTests.end();
for ( itCur = l_LapTests.begin(); itCur != itEnd; ++itCur )
{
cout << (*itCur).m_pTest->GetNum() << endl;
delete (*itCur).m_pTest;
}
getchar();
}

785 名前:781 :04/04/04 06:44
>783
ありがとうございました、そちらの方法で組んで行こうと思います。

786 名前:781 :04/04/04 07:56
>783さんの方法で試してみたのですが、私の環境VC++6.0だと次のコンパイルエラーが発生してしまいました。

error C2664: 'void __thiscall std::list<class CTest *,class std::allocator<class CTest *> >::sort(struct std::greater<class CTest *>)' : 1 番目の引数を 'struct sorter' から 'st
ruct std::greater<class CTest *>' に変換できません。 (新しい機能 ; ヘルプを参照)

なのでsorterを次のように変更してコンパイルエラーは解消することが出来ましたが、l_pTests.sort( sorter() );を実行しても"キタ━━━━(゚∀゚)━━━━ッ!"が表示されず思うようにソートしてくれません。

struct sorter : public std::greater<class CTest *>
{
bool operator()(const CTest *lhs, const CTest *rhs) const {
assert(!"キタ━━━━(゚∀゚)━━━━ッ!!");
return *lhs < *rhs;
}
};

VC++6.0では無理なのでしょうか、それともエラーの修正方法が間違っているのでしょうか?


787 名前:デフォルトの名無しさん :04/04/04 13:24
operator(const Ctest...)ではなく、
operator >(const CTest&, const CTest&) を定義しとけ。

788 名前:デフォルトの名無しさん :04/04/04 13:42
別に関数オブジェクト作るほど気合いれなくても、単なる捨て関数でええんじゃ?

namespace {
  bool Compare(CTest* lhs,CTest* rhs,){
    return lhs->GetNum() < rhs->GetNum();
  }
}

// main内
l_pTests.sort(Compare);


これでとりあえず動くんでない?

789 名前:デフォルトの名無しさん :04/04/04 16:55
私の環境で>788さんの方法をやると次のエラーが出てしまいだめでした。

error C2664: 'void __thiscall std::list<class CTest *,class std::allocator<class CTest *> >::sort(struct std::greater<class CTest *>)' : 1 番目の引数を 'bool (class CTest *,cl
ass CTest *)' から 'struct std::greater<class CTest *>' に変換できません。 (新しい機能 ; ヘルプを参照)
コンストラクタはソース型を持てません、またはコンストラクタのオーバーロード レゾリューションがあいまいです。

>787さんの方法でやってもだめでした。

bool operator>(const CTest& lhs, const CTest& rhs)
{
cout << "キタ━━━━(゚∀゚)━━━━ッ!!" << endl; // 表示されない
return lhs.GetNum() > rhs.GetNum();
}

bool operator<(const CTest& lhs, const CTest& rhs)
{
cout << "キタ━━━━(゚∀゚)━━━━ッ!!" << endl; // 表示されない
return lhs.GetNum() < rhs.GetNum();
}

協力してくださりありがとうございました。

790 名前:デフォルトの名無しさん :04/04/04 17:25
ていうか、VC6でlist::sort()は難しいのかもしれないけど
std::sort()にlistのbegin()とend()を渡してみたら?
比較関数/関数オブジェクトは他の人が書いてるのをそのまま使って。

791 名前:デフォルトの名無しさん :04/04/04 17:27
ああそうか。ポインタのlistか。
operator >(const CTest*, const CTest*)って定義できたっけか?
std::greater< CTest * >を定義しちまう手もあるかも。

792 名前:デフォルトの名無しさん :04/04/04 17:46
>>790
std::sortはRandomAccessIteratorを要求する。

>>971
>operator >(const CTest*, const CTest*)って定義できたっけか?
できない
>std::greater< CTest * >を定義しちまう手もあるかも。
できたとしても好ましくないかと。

793 名前:デフォルトの名無しさん :04/04/04 17:50
じゃあ、std::list< boost::shared_ptr<CTest> >にする手だな。

(boost::shared_ptr自体、std::greater<boost::shared_ptr<T> >を
定義してるけどナ)

794 名前:781 :04/04/05 02:35
>793さんの方法は敷居が高そうなので、今現在は身の程をわきまえて>784の方法で取りあえずしのぐことにしました。

今回のことでC++をまだまだ理解できてないなと痛感しましたので、「プログラミング言語C++ 3rd」を買って勉強することにしました。
そんでもって.NETにさっさと移行したいとも思います。

どうもありがとうございました。

795 名前:デフォルトの名無しさん :04/04/05 13:12
実はlistではなくsetを使っても良い処理だったり。

796 名前:デフォルトの名無しさん :04/04/05 16:20
>「プログラミング言語C++ 3rd」を買って勉強することにしました。

から

>そんでもって.NETにさっさと移行したいとも思います

へなぜ至るのかよくわからん


797 名前:796 :04/04/05 16:22
あー、.NETってVS.NETのことか
だったら勘違いした、すまん


798 名前:デフォルトの名無しさん :04/04/06 09:00

#include <vector>
#include <algorithm>

using namespace std;

struct TEST;

struct test_compared : public binary_function<TEST*, TEST*, bool>
{
 bool operator()(const TEST*& x, const TEST*& y) const
 {
  ユーザー定義の処理
 }
};

int main()
{
 vector<TEST> array;
 ・・(なんらかの処理)・・
 sort(array.begin(), array.end(), test_compared());
 ・・(以下省略)
}


799 名前:798 :04/04/06 09:12
>>798は俺様用メモ
>>792-794はこの俺様用メモを見てもいい。許す。

800 名前:798 :04/04/06 09:48
修正しとく。

×vector<TEST> array;
  ↓
○vector<TEST*> array;

801 名前:デフォルトの名無しさん :04/04/06 09:50
> bool operator()(const TEST*& x, const TEST*& y) const

ここもまちがってるぞ。

802 名前:デフォルトの名無しさん :04/04/06 09:55
まちがいというより、ただの別表現。

803 名前:デフォルトの名無しさん :04/04/06 11:13
>>801
まちがってるって事は、
コンパイル通らないorランタイムエラー発生って事?

是非、模範的な記述方法をお教えくださいな。

804 名前:デフォルトの名無しさん :04/04/06 11:29
#include <list>
#include <iostream>
using namespace std;

class CTest {
private:
 int m_Num;
public:
 explicit CTest(int num) : m_Num(num) {}
 int getNum() const { return m_Num; }
};
struct CTCompare : public binary_function<CTest*, CTest*, bool> {
 bool operator()(const CTest* lhs, const CTest* rhs) const {
  return lhs->getNum() < rhs->getNum();
 }
};

int main(int argc, char* argv[]){
 list<CTest*> ctests;

 for (int i = 0; i < 10; ++i) {
  ctests.push_back(new CTest(rand()));
 }
 ctests.sort(CTCompare());
 list<CTest*>::iterator end(ctests.end());
 for (list<CTest*>::iterator it(ctests.begin()); it != end; ++it) {
  cout << (*it)->getNum() << endl;
 }
 return 0;
}
//自分でdeleteしてね(w

805 名前:デフォルトの名無しさん :04/04/06 12:05
>>804
なるほど、std::less<int*>などはそもそも間違ってるって事ですね。

template<class _Ty>
struct less : binary_function<_Ty, _Ty, bool> {
bool operator()(const _Ty& _X, const _Ty& _Y) const
 {return (_X < _Y); }
};

上のテンプレート(VC6のもの)を参考にしてポインタ型を当てはめてみたんですが、
単なる無意味なアドレス比較に相当するstd::less<int*>などは、
本来エラーが発生しなければいけないって事ですね?
つまり、コンパイラが間違っているorテンプレートが不正って事でOK?

で、模範的な記述に修正すると以下のようにすべきって事ですね。

template<class _Ty>
struct less : binary_function<_Ty, _Ty, bool> {
bool operator()(const _Ty _X, const _Ty _Y) const
 {return (_X < _Y); }
};

806 名前:デフォルトの名無しさん :04/04/06 12:19
強いて言えば、>>804より>>798の方がSTL準拠の記述として正しい。
でも、>>798は他人が見て一瞬戸惑う罠。

807 名前:デフォルトの名無しさん :04/04/06 12:23
>>805
>模範的な記述に修正すると以下のようにすべきって事ですね。
んなこたーない。
つか、やめれ。コピー処理が大量発生する。

808 名前:デフォルトの名無しさん :04/04/06 12:39
>805
ポインタのリファレンスを取るオーバーヘッドが無駄だなぁってことで
>804な感じ

809 名前:デフォルトの名無しさん :04/04/06 13:06
>>798
リファレンスによる実行時のオーバヘッドについては多分ないんだろうけど、
人間様がソース見たときにギョッとするオーバヘッドはあるな、確実にw

810 名前:デフォルトの名無しさん :04/04/06 14:17
>>809
ポインタ位の小さなオブジェクトであれば、わざわざリファレンスにするまでもないと思うし、
むしろ逆に逆参照を2回しなければならない分オーバヘッドは増えるような気がする。
コンパイラが値渡しに最適化するかもしれないけど。

811 名前:デフォルトの名無しさん :04/04/06 14:49
というかこれくらいならまずインライン化されるでしょう.
そのためのfunctorなわけですし.

812 名前:デフォルトの名無しさん :04/04/06 15:21
>オーバヘッドは増えるような気がする。
それは参照がオーバヘッドを生ずると言う意味か?
それは違うと思うが・・・。

813 名前:デフォルトの名無しさん :04/04/06 15:30
>>812
> それは参照がオーバヘッドを生ずると言う意味か?
リファレンスはポインタを用いて実装されているだろうし、参照渡しされたポインタそのものを
更に逆参照しているわけだから、ポインタを値渡しするよりはオーバヘッドは大きくなるはず。

814 名前:デフォルトの名無しさん :04/04/06 15:46
>>813
だったら、参照先を変更できず、また、
参照を使う場合に必ず初期化しなければいけないのは何故?

私的見解だが、コンパイラにとって参照は単なる変数のエイリアスだと思うが?
我々がインスタンスをもった変数と思っているものは
コンパイラにとっては所詮アドレスにすぎず、
同じアドレスと解釈される変数が増えただけという認識なのだが。

リファレンスがポインタで実装されているという明文化された規格などが
あるようであれば教えて欲しい。

815 名前:デフォルトの名無しさん :04/04/06 15:58
>814
関数の引数としての参照がどの変数のエイリアスなのか
コンパイル時に決定できると?(インライン化される場合を除いて)

816 名前:デフォルトの名無しさん :04/04/06 16:04
>>815
ん?
その関数に渡される変数は、そもそもコンパイル時にアドレスが決まるの?
どのアドレス位置で変数用メモリが確保されるかは、スタックの状態次第じゃないの?

817 名前:デフォルトの名無しさん :04/04/06 16:35
>>816
int i;
int &r =i;

上の場合は確かに
>我々がインスタンスをもった変数と思っているものは
>コンパイラにとっては所詮アドレスにすぎず、
>同じアドレスと解釈される変数が増えただけという認識なのだが。
この通りだとは思うのですが,

void f(int & r){ r = 2; }

この場合は,rがどの変数のエイリアスであるかは実行時まで分からないですから

void f(int *const p){ *p = 2; }

とまったく等価(インターフェイスの差異を除いて)であり,
従って参照のdereferenceのオーバーヘッドがかかると思うのですが,どうなんでしょう?

818 名前:デフォルトの名無しさん :04/04/06 17:05
>>817
実行時まで分からないことが、
どうしてオーバーヘッドになると思うの?

逆参照は何も参照変数だけじゃなくて
普通の変数でも普通に行われてるのでは?

819 名前:デフォルトの名無しさん :04/04/06 17:19
void f(int& r):
void f(int i):

上2つは、オーバヘッドは同じ。32ビットだから。
OK?

820 名前:817 :04/04/06 18:24
>>818
assembleも読めないC++初心者なので,何か大きな勘違いをしているのかも知れないのですが

>逆参照は何も参照変数だけじゃなくて
>普通の変数でも普通に行われてるのでは?
確かにそうだと思います.ですが,例えば819さんの例では
(関数の呼び出しの部分「だけ」に関しては819さんの言うとおりだと思います)

void f(int i/*スタックにiが置かれそのアドレスが引き渡される*/){
i; // 引き渡されたアドレスをdereferenceして値iを得る
}

void f(const int & r/*スタックにint*が置かれそのアドレスが引き渡される*/){
r; // 引き渡されたアドレスをdereferenceしてint*の値を得て,
//さらにそのint*をdereferenceして(参照の場合ここが余計にかかる)intの値を得る.
}

こういうイメージだったのですが何か間違っているのでしょうか?


821 名前:デフォルトの名無しさん :04/04/06 18:33
>>818
> 逆参照は何も参照変数だけじゃなくて普通の変数でも普通に行われてるのでは?
参照の場合は逆参照が1つ余計に必要になり、それがオーバヘッドになるということじゃないの?

Tへの参照を引数に取る関数は、Tへのポインタを引数に取る関数としてコンパイルされるとすると、
Tへのポインタ型の仮引数を読んで、更にそのTへのポインタ型の値を逆参照する必要がある。

それに対して、T型を値渡しで引数に取る関数は仮引数を読むだけでいい。

明らかに1回の余計な逆参照が生じている。逆参照の存在が問題なのではなく、その回数が問題になる。

> 実行時まで分からないことが、どうしてオーバーヘッドになると思うの?
実行時まで判らないのは、生成されるコードではなくて参照されるオブジェクトの位置でしょ。
参照が前述の様な実装をされているとすれば、引き渡されるポインタの値。
それが違うことによって、実行速度が変化するとは思えない。

822 名前:デフォルトの名無しさん :04/04/06 18:40
ぶっちゃけ参照は常に逆参照されるポインタです、みたいなことが
禿の本に書いてあったような気がする

823 名前:デフォルトの名無しさん :04/04/06 18:50
>>820
おk

824 名前:_ :04/04/06 19:44
gccは$を識別子として使えるけど、VCではどうなん?

825 名前:_ :04/04/06 19:45
あ、さげてしまた。

826 名前:デフォルトの名無しさん :04/04/06 20:21
>>820
間違ってないと思いますよ。
以下VS.net2003での最適化無しの場合です。
アセンブラ読めなくてもなんとなくわかってもらえるかと。

void test(int& a)
{
printf("a:%d", a);
}
mov eax,dword ptr [a]
mov ecx,dword ptr [eax]
push ecx
push offset string "a:%d"
call _printf
add esp,8

void test(int a)
{
printf("a:%d", a);
}
mov eax,dword ptr [a]
push eax
push offset string "a:%d"
call _printf
add esp,8


827 名前:デフォルトの名無しさん :04/04/06 23:02
>>826
VC++6.0で確認したが
f(int a){ printf("a:%d", aaa); }
f(int& a){ printf("a:%d", aaa); }
f(int* a){ printf("a:%d", *aaa);}
がいずれも同じコードになった。
全く同じだった。VS.NETは違うんだね。
以下、混合モードから抜粋。
3つとも一緒だったの1つだけ貼る。

push ebp
mov ebp,esp
sub esp,40h
push ebx
push esi
push edi
lea edi,[ebp-40h]
mov ecx,10h
mov eax,0CCCCCCCCh
rep stos dword ptr [edi]
mov eax,dword ptr [ebp+8]
push eax
push offset string "a:%d" (0043d01c)
call printf (00408900)
add esp,8

828 名前:デフォルトの名無しさん :04/04/06 23:17
>>822
ぶっちゃけ、参照だけじゃなく変数はすべて逆参照されるポインタ
その本の内容は言葉足らず。もしくは間違っている。

829 名前:デフォルトの名無しさん :04/04/06 23:36
>>828
> ぶっちゃけ、参照だけじゃなく変数はすべて逆参照されるポインタ

その主張でレジスタ上の変数はどう説明されるのでしょう?

830 名前:デフォルトの名無しさん :04/04/06 23:49
最適化によって発生したレジスタ変数は、逆参照の手間が省かれた変数・・かな?
何にせよ、参照変数オーバヘッド伝説は 糸冬 了。

831 名前:デフォルトの名無しさん :04/04/06 23:53
> 最適化によって発生したレジスタ変数は、逆参照の手間が省かれた変数・・かな?

関数の引数で、値渡しならレジスタに乗るものが参照渡しだと乗せられない。
現実的な差があるだろ。

832 名前:デフォルトの名無しさん :04/04/06 23:54
>>827って同じコードになるわけないと思うんだけど

833 名前:デフォルトの名無しさん :04/04/07 00:02
>>832
VC++6.0持ってない?
私に確認するより、デバッグで混合モードを見て頂けると有難いのだが。

違っているのを報告してもらえれば万事解決。

834 名前:デフォルトの名無しさん :04/04/07 00:12
>>827
それだと最適化されてるかなんか勘違いしてると思う。
その出力コードだとたとえばポインタ版だと
aのアドレスではなくaの中身がスタックに直接積まれてるので
関数内でaのアドレスが参照できないよ。


835 名前:デフォルトの名無しさん :04/04/07 00:14
ちなみにVC++6.0では、引数の積み上げ方は違ってた。投稿の制約上、改行を一部変えた。
void Func1(int aaa){printf("a:%d", aaa); } void Func2(int* aaa){printf("a:%d", *aaa);}void Func3(int& aaa){printf("a:%d", aaa);}
int main(){
int num = 100;int* p_num = #
Func1(num);Func2(&num);Func2(p_num);Func3(num);
return 0;
}
=====以下、混合モードの表示======
34: Func1(num);
00401185 mov ecx,dword ptr [ebp-4]
00401188 push ecx
00401189 call @ILT+25(Func1) (0040101e)
0040118E add esp,4
35: Func2(&num);
00401191 lea edx,[ebp-4]
00401194 push edx
00401195 call @ILT+40(Func2) (0040102d)
0040119A add esp,4
36: Func2(p_num);
0040119D mov eax,dword ptr [ebp-8]
004011A0 push eax
004011A1 call @ILT+40(Func2) (0040102d)
004011A6 add esp,4
37: Func3(num);
004011A9 lea ecx,[ebp-4]
004011AC push ecx
004011AD call @ILT+10(Func3) (0040100f)
004011B2 add esp,4

836 名前:デフォルトの名無しさん :04/04/07 00:19
>>834
(;´Д`)私に言われても・・・。
VC++.NET版を張ってくれるヤシは居らんかね?

837 名前:デフォルトの名無しさん :04/04/07 00:37
void f1(int & i) { printf("%d\n", i); }
void f2(int * i) { printf("%d\n", *i); }
void f3(int i) { printf("%d\n", i); }

このコードをg++ -S すると以下の出力が得られました。

ttp://do.sakura.ne.jp/~junkroom/cgi-bin/megabbs/readres.cgi?bo=lounge&vi=999294620&res=148

長くなったので宿題スレッドのアップローダにあげてあります。

838 名前:デフォルトの名無しさん :04/04/07 00:39
.net2003の最適化無しだとポインタ版と参照版は同じコードになるよ。
void test(int* a)
{
printf("%p:%d", a, *a);
}
mov eax,dword ptr [a]
mov ecx,dword ptr [eax]
push ecx
mov edx,dword ptr [a]
push edx
push offset string "%p:%d"
call _printf
add esp,0Ch


839 名前:デフォルトの名無しさん :04/04/07 01:04
正直、こんなオーバヘッドよりも
ロジックとかアルゴリズムの方が
実行速度にはるかに影響を与えている罠。

840 名前:デフォルトの名無しさん :04/04/07 01:09
827の修正します。スマソ。(´・ω・`)
あらたにvoid Func4(int*& aaa);も追加して試してみた。
3つ一緒というのは間違いでした。

同じだったのは、void Func2(int* aaa)とvoid Func3(int& aaa)。
void Func1(int aaa)はコードが1つ少ない。
void Func4(int*& aaa);はコードが1つ多い。

よって、VC6.0++では、

1.(int )
2.(int* )、(int&) 同等
3.(int*& )

の順番にコードが短い。お騒がせしました。

841 名前:840 :04/04/07 01:12
>>834
>なんか勘違いしてると思う。

その通りだったみたいです。失礼しました。
GCC、VC6.0、VC.NETいずれの場合も
int* int& が同じコードを吐くという事でよろしいでしょうか?

842 名前:デフォルトの名無しさん :04/04/07 02:21
実際、int*とint&はどのコンパイラでもほぼ同じ扱いと仮定してかまわないけれど、
inline関数で&で受けるもの(特にconst&)は、うまく最適化される場合もあった気がする。
*で受けると配列かどうかわからないけど、&で受けると配列ではないことがわかるから。

843 名前:デフォルトの名無しさん :04/04/07 12:20
>>827は真性か?(禿藁

844 名前:_ :04/04/07 14:57
クラス内で文字列定数を定義したい場合どうするんですか?
static const char* str[] = { "a", "b", "c" };
は駄目でした。

845 名前:デフォルトの名無しさん :04/04/07 15:32
//宣言
class Hoge{
static const char* str[];
};
//定義
const char *Hoge::str[] = {"a","b","c"};
だったか。

846 名前:デフォルトの名無しさん :04/04/07 15:53
>>844
なんか別のスレでも同じような回答をしたばかりなのだが・・・

クラス宣言内で初期化できるのは static constな整数だけ。
それも即値でしか初期化できない。

これ以外の静的メンバは必ずクラス宣言外で定義が必要だし、
そこで初期化するしかない。

なお、クラス宣言内で初期化した static constな整数には実体がない。
実体が必要になるときは、これまたクラス宣言外で定義が必要。

以上禿本から要約。

847 名前:_ :04/04/07 16:08
>>845,846
どうも親切に。質問する前に他スレも読みますね。

848 名前:デフォルトの名無しさん :04/04/07 23:59
class A
{
public:
template<class T> T* func()
{ return (T*)NULL; }
};

template<typename T> T* func()
{ return (T*)NULL; }


A a;
int* p1 = func<int>(); // (1)OK
int* p2 = a.func<int>(); // (2)error C2062: 型 'int' は不要です。


(1)が良くて(2)がダメな理由がわかりません。
なぜメンバ関数だとダメなのでしょうか?

849 名前:848 :04/04/08 00:01
class Aの方の template<class T> は template<typename T> です。
どっちでも同じですけど。


850 名前:848 :04/04/08 00:08
書き忘れました。VC++6.0 SP6です。

851 名前:デフォルトの名無しさん :04/04/08 00:11
VC6でテンプレートをがんばるなヨー
諸般の事情があるなら別だけどさ、SP6入れてるってことは遊びだろ?

852 名前:デフォルトの名無しさん :04/04/08 00:15
VC++ .NET 2003では通りました.
851さんのおっしゃるとおりVC6でテンプレートを使うのはお勧めできません.

853 名前:848 :04/04/08 00:22
>>851-852
VC++6.0のテンプレートってバグバグなんですかorz
だれか2003くれないかな・・・

854 名前:デフォルトの名無しさん :04/04/08 00:44
VC7.0の最適化は、ツボにはまると最悪です。
それ考えるとVC6.0の方がまだマシだとおもふ。


855 名前:デフォルトの名無しさん :04/04/08 01:38
int* p2 = a.template func<int>();
とやってもだめか?本来は冗長な書き方だが。


856 名前:848 :04/04/08 09:42
>>855
error C2951: テンプレートの宣言はグローバル スコープまたは名前空間スコープでだけ可能です。
error C2059: 構文エラー : 'newline'

と出ました。

857 名前:デフォルトの名無しさん :04/04/08 10:16
>>856
困ったのう。

858 名前:デフォルトの名無しさん :04/04/08 10:19
つーか、NULLポインタ渡すだけなのになぜ、テンプレートつかうのかと。
普通にNULLいれればいじゃん。


859 名前:848 :04/04/08 10:23
>>858
例として挙げただけで、実際とは違います。

860 名前:デフォルトの名無しさん :04/04/08 12:46
ちょっと掴み所のない質問かもしれませんがよろしくお願いします。

MIDIアプリで、
txtに変換されたMIDIデータを読みこんで、設定した伴奏を自動で(txtで)付け加え、
それをMIDIに戻す、というのを作ろうとしています。

伴奏を付け加えるのは何とかできそうなんですが、
肝心のMIDIデータの吸い出し方が判りません。

良い本やHPなど紹介して頂ければと思います。よろしくお願いします。

861 名前:デフォルトの名無しさん :04/04/08 12:52
スレ違い。
ハイ、次の方どうぞ

862 名前:デフォルトの名無しさん :04/04/08 18:05
string から vector<char> にデータを写す時の定石的な書き方ってありますか?
memcpy で普通にコピーみたいな感じでしょうか?

863 名前:デフォルトの名無しさん :04/04/08 18:24
>>861
判らないからってそそういう言い方はないだろう。
ま、俺もわからんけど。

864 名前:デフォルトの名無しさん :04/04/08 18:41
>>862

vector<char> c;
string s;
c.assign(s.begin(), s.end());

865 名前:863 :04/04/08 18:50
と言いつつHPツラツラ見てたらこんなんあったぞよ。
MIDIのデータ構造ってどうなってるんですか、っていう立派な質問ではある。
初心者も来る所だから、すれ違いで気に入らん人は文句言うだけでなく誘導すべし。

ttp://www.pluto.dti.ne.jp/~daiki/Midi/Midi.html

866 名前:862 :04/04/08 19:03
>864
そうか、vector<char> -> string とまったく逆に書けばよかったんですね…
ありがとうございました

867 名前:デフォルトの名無しさん :04/04/08 19:23
おいおい、すれ違いの質問を「立派な質問」かよw

868 名前:デフォルトの名無しさん :04/04/08 19:37
本物のバカみたいだから放置していいんじゃないかな。

869 名前:デフォルトの名無しさん :04/04/08 20:57
>>862
ちなみにmemcpyを使うなら下の書き方かな?

vector<char> v;
string s;
v.resize(s.size());
memcpy(&v[0], s.c_str(), s.size());

870 名前:デフォルトの名無しさん :04/04/08 21:01
>>869
s.c_str()よりは、&s[0]のほうがいいかも?

871 名前:デフォルトの名無しさん :04/04/08 21:13
>>870
stringは要素が連続した領域に格納されることが保証されているの?
vectorは問題ないはずだけどね。

872 名前:デフォルトの名無しさん :04/04/08 21:18
>>871
保証されてなかったら、string::c_str()なんて関数を公開しない罠。
むしろ、vectorじゃないか?保証がないのは。

873 名前:デフォルトの名無しさん :04/04/08 21:30
>>872
EffectiveSTLだったか何かにvectorの連続性は保証されるって書いてあったと思うぞ。

874 名前:869 :04/04/08 21:30
>871
私も疑問に思ったので標準を漁りました.
まず,周知の通りvectorは&v[0]で取れるメモリの連続性は保証されています.
一方でstringは内部表現が連続したメモリであることは保証されていません.
(標準の21には空間の連続性に対する表明が見つかりませんでした)
また,Effective STLの第16項も同様に言っています.
そして,string::c_strは必ずしも内部表現の配列の先頭を返すとは限らないようです.
(標準21.3.6)

>872
むしろ内部の連続性が保証されていないのでc_strを公開している,というのが正しいようです.

875 名前:デフォルトの名無しさん :04/04/08 21:32
いや、stringの内部でどう並んでるかは何の保証もない。
c_strは、内部表現を得るための物ではなく、
stringと意味的に等しい物を得る物だよ。

876 名前:デフォルトの名無しさん :04/04/08 21:33
std::string は参照カウントで実装されうる品

877 名前:869 :04/04/08 21:35
ん?ということは,c_strをmemcpyに引き渡すという行為はかなり無駄な行為なのかも知れませんねw
c_strが中でstringの内部表現をコピーしているのかも知れませんから.(ここは実装依存でしょう)
というわけでおとなしくiteratorを使うのが良いのでしょう.>864

878 名前:デフォルトの名無しさん :04/04/08 21:39
例えばforループの中である処理をやっていて、
キーが何か押された場合別の処理に進む方法っていうのは何かありませんか?


879 名前:デフォルトの名無しさん :04/04/08 22:08
>>874
>むしろ内部の連続性が保証されていないのでc_strを公開している,というのが正しいようです

では、どんな時にc_str()を使うのか教えていただきたい。
cのヌル終端文字列だからc_str()って名前なんじゃないかと思うのですが・・・。
つまり、C標準関数やその他の関数のconst char*引数に使うための代物では?
保証されないという事は、stringの文字列バッファの中身をCの関数に渡しちゃダメって事ですよね。

vecorのような1つの要素が大きな容量である配列の連続性が保証されていて、
stringのような1つの要素が1バイトである配列の連続性が保証されていないのは知りませんでした。
明らかな連続性を前提にしているから明記してないだけだとばかり思ってました。

そうであれば、stringから従来型のchar[]へ、バッファコピーする際の推奨されるコピー方法は何でしょうか?

880 名前:デフォルトの名無しさん :04/04/08 22:19
>>879
std::stringの内部表現がCの文字列と全く互換性がない場合にはc_str()が互換性のあるものに
コンバートしてそれを返すだけ。よってstrcpy等のソース側にはc_str()を渡せる

881 名前:デフォルトの名無しさん :04/04/08 22:23
お前ら

882 名前:デフォルトの名無しさん :04/04/08 22:29
basic_string<charT>::operator [](int index)はdata()[index]を返す。[21.3.4 1]
data()はcharT *を返す。イテレータではなく連続した領域へのポインタである。[21.3.6 4]
つーことは(s.size() > 0なら) &s[0] は s.data() と同等であり、連続した領域の
先頭アドレスが得られるはずだな。

883 名前:デフォルトの名無しさん :04/04/08 22:30
>>880
回答ありがとうございました。
今までどおりc_str()でconst char*に使う事にします。
iteratorではC関数に渡すときアドレスが連続じゃないかもしれないみたいなので。

884 名前:デフォルトの名無しさん :04/04/08 23:41
>>872
std::ropeにもc_str()があるわけだが。

885 名前:デフォルトの名無しさん :04/04/08 23:55
むむむ?いつの間に標準にropeが入ったんでしょうか?

886 名前:デフォルトの名無しさん :04/04/09 00:29
>>885
どこに標準の話をしていると書いてあるよ?

887 名前:デフォルトの名無しさん :04/04/09 01:15
>>879
> stringから従来型のchar[]へ、バッファコピーする際の推奨されるコピー方法
そらやっぱり string::copy() なんじゃないの?


888 名前:デフォルトの名無しさん :04/04/09 02:02
Effective STLの日本語正誤表orここは気をつけたほうがいいというアドバイスないっすか?
ピアソン覗いたら英語しかないっす・・・。
(というかピアソンは用意してないっす)
当方、本の間違いに気づけるほど力ないっす(´・ω・`)

889 名前:デフォルトの名無しさん :04/04/09 03:37
>>886
>『std::』rope
って書いてあるからじゃ? 標準じゃなきゃ、std内には入れられないんじゃなかったっけ?
だからいつのまに標準に、と聞いてるのかと。

890 名前:デフォルトの名無しさん :04/04/09 03:48
>>889
STLportとかSGI STLじゃん。知らんのか?標準ではなくても
std::に入っている。

891 名前:デフォルトの名無しさん :04/04/09 04:49
>>890

892 名前:デフォルトの名無しさん :04/04/09 07:46
SetTimerをC言語のコンソールアプリで使う方法を教えてください。

893 名前:デフォルトの名無しさん :04/04/09 07:49
>>892
Win32APIスレに逝くべきだよ。

894 名前:892 :04/04/09 07:52
SetTimer(NULL,NULL,FUNC,100); としてもFUNCが全くコールバックされません。何故でしょうか?

895 名前:892 :04/04/09 07:52
SetTimer(NULL,NULL,FUNC,100); としてもFUNCが全くコールバックされません。何故でしょうか?


896 名前:デフォルトの名無しさん :04/04/09 07:53
>>892
というより、スレの趣旨が判らないほどに理解が混乱しているのなら、
むやみに質問を書き込まずに冷静に頭を整理した方がいいよ。

897 名前:デフォルトの名無しさん :04/04/09 08:03
すいません、API専用のスレがあるとは知りませんでした。

898 名前:デフォルトの名無しさん :04/04/09 09:50
BCBでいうところの__closureみたいなことをやりたくて考えてみました。
で、できたのが次のような方法。実験はVC6で行いました。

【定義】
typedef void (CObject::*METHOD_HANDLER)(CObject *Sender);
// たとえばメインフレームクラス
class CMainFrame : public CFrameWnd
{
  :
private:
  void MainFrameHandler(int Hoge);
  :
};

【使うとき】
CObject *pInstance;
METHOD_HANDLER pHandler;

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  :
  :
  pInstance = this;
  pHandler = (METHOD_HANDLER)&CMainFrame::MainFrameHandler;
}

で、使うときはこんな具合。

  pInstance->*pHandler(5963);

一応意図した動作はしていますが、こんなんで大丈夫なんでしょうか。
インスタンスとオフセット情報さえあれば型は何でもいいのかな?

899 名前:898 :04/04/09 09:52
ごめん、ちょっと間違えた。

×typedef void (CObject::*METHOD_HANDLER)(CObject *Sender);
       ↓
○typedef void (CObject::*METHOD_HANDLER)(int Hoge);

900 名前:デフォルトの名無しさん :04/04/09 10:08
>>889-890
標準ではないものがstd名前空間に入っていることは、規格上あり得ない。
なので std::rope という表現ができること自体、規格違反。

889が正しい。

901 名前:デフォルトの名無しさん :04/04/09 16:47
>>900
ならお前はSTLportは一切使うな。これでOK。

902 名前:デフォルトの名無しさん :04/04/09 16:53
>>901
(・∀・)ニヤニヤ

903 名前:デフォルトの名無しさん :04/04/09 17:01
STLportって標準外のも含んでるんじゃなかった?
ハッシュコンテナとかC++標準じゃないよね?

904 名前:デフォルトの名無しさん :04/04/09 17:36
>>903
STLportはSGI STLを改良し続けて、事実上のフリーソフトに
なっている。だからstd::ropeやstd::hash_map、std::slistや
std::identity、std::project(他にもたくさん)を含んでいる。これ
はSGI STL直系のSTLである事を示している。

それらは標準外である事は十も承知だし、移植性を問題に
する場合は一切使ってないが(というかあまり使わないよね)、
どうも>>900は俺がそれらの標準外のコンテナや関数オブジェクト
を標準であると勘違いしていると思いこんでいるらしく、しつこく
規格違反だとかstdに入れるべきでないとか的はずれなレス
ばかり返しやがる。

随分と標準がお好きなようだな>>900は。

905 名前:デフォルトの名無しさん :04/04/09 17:45
> また、テンプレートライブラリ(STL含む)に関する質問は
> 専用の別スレへどうぞ。
ここって 結構ピュアなC++スレでしょ?ちがったっけ?

906 名前:デフォルトの名無しさん :04/04/09 17:51
参照にオーバーヘッドはないとか主張してた厨だろ

907 名前:デフォルトの名無しさん :04/04/09 17:53
>>904
なんか論点をあさっての方向に勘違いしてねぇか?
現状のSTLportがどうなってるかなんてのは問題じゃなくて、単に
「標準C++で規定されてないものをstd名前空間に入れるのは行儀悪い」
ってだけの話だろ?

908 名前:デフォルトの名無しさん :04/04/09 18:06
>>907
おいおい、俺のレスをちゃんと読んでから書いてるのか?
「標準C++で規定されてないものをstd名前空間に入れるのは行儀悪い」
という点については否定してないだろ。

STLportの行儀悪さについては「十も承知」とちゃんと書いてるだろ。
何が言いたいんだよ。

909 名前:デフォルトの名無しさん :04/04/09 18:08
>>907
その通りだけど、>>901=>>904 がかわいそうだから、もう勘弁してあげようよ。

910 名前:デフォルトの名無しさん :04/04/09 18:35
たった今>>907>>909は他人のレスを読まずに自分のレス
を返す文盲厨だと証明されますた。

911 名前:デフォルトの名無しさん :04/04/09 18:52
>901=>904=>908=>910
(・∀・)ニヤニヤ

912 名前:デフォルトの名無しさん :04/04/09 19:01
もうどっちでもいいからC++の話しようぜ?

913 名前:デフォルトの名無しさん :04/04/09 21:15
>>912
次スレまではこの流れでキボンヌ。(ワラ

914 名前:デフォルトの名無しさん :04/04/09 21:21
>>913
同意(w

ここまでベタな (・∀・)ニヤニヤ はあんまりいないしね。
春も終わっちゃうから最後のお楽しみ。

で、rope.c_str() で何が言いたかったの?

915 名前:デフォルトの名無しさん :04/04/09 21:49
俺は別のところにつっこんじゃうぞ。

>>904
http://www.google.co.jp/search?hl=ja&ie=UTF-8&oe=UTF-8&c2coff=1&q=%E4%B8%80%E3%82%82%E6%89%BF%E7%9F%A5&lr=
http://www.google.co.jp/search?q=%E5%8D%81%E3%82%82%E6%89%BF%E7%9F%A5&ie=UTF-8&oe=UTF-8&hl=ja&lr=
http://www.google.co.jp/search?hl=ja&ie=UTF-8&oe=UTF-8&c2coff=1&q=%E7%99%BE%E3%82%82%E6%89%BF%E7%9F%A5&lr=
http://www.google.co.jp/search?hl=ja&ie=UTF-8&oe=UTF-8&c2coff=1&q=%E5%8D%83%E3%82%82%E6%89%BF%E7%9F%A5&lr=
http://www.google.co.jp/search?hl=ja&ie=UTF-8&oe=UTF-8&c2coff=1&q=%E4%B8%87%E3%82%82%E6%89%BF%E7%9F%A5&lr=

916 名前:デフォルトの名無しさん :04/04/09 23:16
>>915
「百も承知」と書いて欲しかったのかよ。完全な重箱の隅を突く
アホだな。

>>914
何がニヤニヤだよ。反論できないだけだろ知障。

917 名前:デフォルトの名無しさん :04/04/09 23:25
プラットホームをまたいでコーディングするPGにとって
標準STLの正しい理解は極めて重要。

たまに病的なまでに規格に詳しい人もいるが、
まあ、みんなに良い知識を提供してくれるのだから歓迎すべきだね。

918 名前:デフォルトの名無しさん :04/04/09 23:56
テンプレートライブラリがなけりゃC++を使えないような香具師が
わかったような口を利くな。

919 名前:デフォルトの名無しさん :04/04/10 00:01
( ゚д゚)<

920 名前:デフォルトの名無しさん :04/04/10 00:04
たまに居るよな、テンプレートを使わず自力でリストを準備したりする輩。
で、破滅的なソースを書いて、プロジェクトから外される。

そして、あとを引きついだ人間が酷い目にあう、と。
アフォプロジェクトの黄金パターンだな。

921 名前:デフォルトの名無しさん :04/04/10 00:14
>901の流れはどうつながってるの?
漏れの印象では>916>918ときてるように思ったんだが


922 名前:デフォルトの名無しさん :04/04/10 06:57
というか、だれか>>898にレスしてやれ。
ここまでスルーされているのも泣ける。

923 名前:デフォルトの名無しさん :04/04/10 11:52
"C++プログラミング言語 第3版"に出てくる
練習問題の模範解答みたいなものって、どっかにありますか?

924 名前:デフォルトの名無しさん :04/04/10 12:15
>>923
え?知らないのか?
「プログラミング言語C++:ソリューション」、アジソン・ウェスレィ/アスキー、
ISBN4-7561-3136-0

英語名は「C++ Solutions Companion to The C++ Programming Language,
Third Edition、author: David Vandevoorde」だから適当にぐぐると
PDFやCHMぐらいは落ちてるかも。(できるだけ買おう)

925 名前:デフォルトの名無しさん :04/04/10 15:35
相互参照はどうすれば可能なのでしょうか?
(試したコード:エラー)
struct B;
struct A
{
void test(B& b){b.hello();}
};
struct B
{
void test(A& a){}
void hello(){}
};
int main(){}

926 名前:デフォルトの名無しさん :04/04/10 15:43
struct B;
struct A
{
void test(B& b);
};
struct B
{
void test(A& a){}
void hello(){}
};
void A::test(B& b){b.hello();}
これでどーよ?

927 名前:925 :04/04/10 15:49
>>926
できました!
void A::test(B& b){b.hello();}
をBの定義の後に記述すればよいのですね。


928 名前:デフォルトの名無しさん :04/04/10 18:23
規格書とかEffective STLとか手元にあるんだけど
The C++ Standard Libraryも手元にあったほうが良いのかなぁ?

929 名前:デフォルトの名無しさん :04/04/10 19:55
Effective C++ の46項の、enum値をコピー不可クラスにすることでランタイム時チェックから
コンパイル時チェックにするっていうのは、初めはすげーと思ったけど、めんどくさすぎで
現実的ではなさすぎ。
なんかうまいこと簡単にやってくれるようなクラステンプレートみたいなもんはないかね?
boost::noncopyable使うだろう、というところで俺の頭はパンクした。

930 名前:デフォルトの名無しさん :04/04/10 20:54
初めて大きいプログラムを作り始め、複数ソースで作っています。
そこで変数の宣言についての質問なのですが、
Aというクラスがあり、A.cpp内でしか使われない変数というのは
Aのプライベートメンバ変数として宣言するのがいいのか、それともA.cppの中で
グローバル変数(staticをつけて)として宣言した方がいいのでしょうか。
Aオブジェクトが複数存在する可能性がある場合はグローバル変数として宣言するしかないと思いますが、
ひとつしか存在しない場合はどちらも同じような気がします。
どなたかアドバイスよろしくお願いします。

931 名前:デフォルトの名無しさん :04/04/10 21:03
static でクラス変数にしたらいんでない?

932 名前:デフォルトの名無しさん :04/04/10 21:13
あ、そんな方法が…
すいません。激しく出直してきます。
ちなみにstaticで解決できるわけですが、A.cppのグローバル変数とどちらがよいか、
というのはありますか?

933 名前:デフォルトの名無しさん :04/04/10 21:19
そりゃまぁ、オブジェクト指向したいならグローバル変数はなるべく避けるべきだろうね。

934 名前:デフォルトの名無しさん :04/04/10 21:28
>>930
逆だよ。グローバル変数だとインスタンスが複数になるときに困る。

935 名前:デフォルトの名無しさん :04/04/10 22:01
>932 リンカからみた名前空間を汚染したいかどうか。

936 名前:デフォルトの名無しさん :04/04/10 22:16
Vector配列を数字の小さい順にソートする関数はありますか?

937 名前:デフォルトの名無しさん :04/04/10 22:17
std::sort()

938 名前:デフォルトの名無しさん :04/04/10 22:37
VC C++ Standard Edisionでの
ソリューションエクスプローラの項目が表示メニューを見ても
見つかりませんでした。
どこにあるのか教えてください。

939 名前:デフォルトの名無しさん :04/04/10 22:50
>>938
すれ立てるまでも無い・・・の100か?だったらVC6にはソリューションエクスプローラは無い。
つーかスレ違い

940 名前:938 :04/04/10 23:22
>>939
ありがとうございました。
そしてスレ違いごめんなさい

941 名前:デフォルトの名無しさん :04/04/11 00:08
>935
930にstatic付き、って書いてあるよ。
まあC++的には無名名前空間だろうけど。

>932
基本的にクラスに関係するものならクラスの中に入れるべきだが、
何か理由があって、ヘッダに宣言を書きたくない場合はソースに埋め込む。

942 名前:デフォルトの名無しさん :04/04/11 01:19
というか、どっちでもいいときはスコープは小さい方にしとけ。
これはもう格言だから。

#たとえば、「インスタンスが一個しかない」という前提を忘れた時に
#まとめて不幸がやってくるだろ?


943 名前:デフォルトの名無しさん :04/04/11 03:20
それならばインスタンスが1個しかできないような
コーディングをしない方が悪いと思うが。

944 名前:デフォルトの名無しさん :04/04/11 03:27
>>942
Singletonにしてもだめか?

945 名前:942 :04/04/11 03:44
>>943-944

だから、「たとえば」の話。
それに、Singletonだからグローバルの方がいいって話にはならんでしょ。

946 名前:929 :04/04/11 03:53
( ´-`).。oO(俺の質問は華麗にスルーですかそうですか (つwT))

947 名前:928 :04/04/11 04:22
えっと・・・あの・・・できれば私のも・・・
だいたい分かっている(つもり)なんですが役に立つでしょうか?
5000円(でしたっけ?)は結構大きい出費なので

948 名前:デフォルトの名無しさん :04/04/11 05:09
>947
あった方が良いかなんて人それぞれだろ
何が必要なのか、人に聞くのもいいがちったあ自分でも考えろや
それでも分からんのなら、このスレに出てきた書籍全部買え


949 名前:デフォルトの名無しさん :04/04/11 07:14
便乗質問で申し訳ありませんが、
グローバル変数を使ったときにインスタンスが複数になった場合の不都合とは
具体的にどのようなものなのでしょうか?
自分はC++とDirectXでゲームを作っておりまして、
頂点バッファ・テクスチャへのポインタなどをA.cppのstatic変数として宣言しております。
(staticメンバにしたほうがよいというのはこのスレをみて知りました…)
それでAの関数であるDraw();内で使っています。
これは複数でも単体でも今のところ不都合はありません。
>>942さんの格言通りこれからコーディングしなおすつもりではありますが
これから何かで使うかもしれないので複数になると出る不都合を教えていただけないでしょうか?
よろしくお願いします。

950 名前:デフォルトの名無しさん :04/04/11 09:42
>>941

そうだね。C++的には無名空間。
staticは推奨されてないからね。

なんでstaticを使わないことを推奨されてるのかは、知らない。
誰か教えて。

ヘッダに書きたくないときは pimpl にすればよろし。


951 名前:デフォルトの名無しさん :04/04/11 09:45
>>947

948の言うとおり。

928がどんな奴なのかわからないと、
無いよりあった方が良いとしか言えない。

俺は持ってないけどな。

952 名前:デフォルトの名無しさん :04/04/11 09:50
>>949
オブジェクト指向について、一度勉強しなさい。
その変数がオブジェクトの状態をあらわしてたら困るでしょ。

お勧めとは言い切れないけど、このサイトとかを参考にどぞー。
http://kmaebashi.com/programmer/object/intro.html

953 名前:初心者 :04/04/11 10:28
動的配列をvectorであてて

vector<int> a(N);

なんか操作

delete a?

とdeleteする時はどうすればいいのでしょうか?

954 名前:デフォルトの名無しさん :04/04/11 10:39
内部で管理しているメモリはデストラクタで解放されるから何もせんでいい。

new したポインタを要素にしているという話なら(おすすめしないが)
それぞれの要素を注意深く手動で解放しないといかん

955 名前:デフォルトの名無しさん :04/04/11 11:00
例を見るに、そこまで判っていないんじゃないかと。

int i;
として
delete i;
はしないだろ?
と言っておく。

int *pInt = new int;
としたら
delete int;
が必要。

vector<int>という型(クラス)なので、
vector<int> a;
にdeleteはいらない。

OK? >953

956 名前:デフォルトの名無しさん :04/04/11 13:01
>>953
つーか、初心者を剽窃したいなら初心者スレに逝けよ。

957 名前:デフォルトの名無しさん :04/04/11 13:03
初心者を剽窃アゲ


958 名前:デフォルトの名無しさん :04/04/11 14:56
辞書で調べてみたけど全然意味が違うな。

959 名前:942 :04/04/11 15:03
>>949

「グローバル変数はどこからでも誰にでも参照も変更できる」
ということは、つまりプログラムを修正したい場合、*全*ソース
コードを舐め回して影響が無いかどうかをチェックする必要が
あるということ。プログラムの規模が大きくなればなるほど、
この影響は無視できなくなる。

staticにすれば、影響範囲はClassの中だけにとどまる。
ローカルにすれば、関数内だけにとどまる。

というか、オブジェクト指向でいくんなら、
もはやグローバルという用語は忘れて
「Publicか」「Privateか」という思考に切り替えた方がいいよ。


960 名前:デフォルトの名無しさん :04/04/11 15:20
ちょっと聞きたいんだけど
vector<void*> v;

色々

vector<vector<void*>::iterator> v2;
for (vector<void*>::iterator it = v.begin(); it != v.end(); ++it)
{
    if ( /* it はもう必要ないなら*/ )
    {
        v2.push_back(it);
        delete (*it);
    }
}

for (vector<vector<void*>::iterator>::iterator it = v2.begin(); it != v2.end(); ++it)
    v.erase(*it);

っていうコードなんだけど、もっと綺麗に書く方法ないかな?

961 名前:初心 :04/04/11 15:37
Borland C++ 5.5インストールしたんだけどどうすりゃいいの?
.cppってファイル作ってどうすりゃいいの?
もうわかんない…

962 名前:デフォルトの名無しさん :04/04/11 15:46
>>960
typedef vector<void*>::iterator iterator;
iterator const end = v.end();
iterator end_of_the_held = v.begin();
for (iterator it = v.begin(); it != end; ++it)
{
  if ( /* it はもう必要ないなら*/ )
  {
    delete *it;
  }
  else
  {
    *end_of_the_held = *it;
    ++end_of_the_held;
  }
}
v.erase(end_of_the_held, end);

963 名前:デフォルトの名無しさん :04/04/11 15:56
std::vector<void*>をboost::shared_ptrで包む。

964 名前:デフォルトの名無しさん :04/04/11 16:04
>>961
Borland C++ Compiler 5.5.1とTurbo Debugger 5.5の入手から簡単な使用までのガイド
http://www.cmagazine.jp/beginner/bcc/
タダで使えるBorland C++ Part3
http://pc5.2ch.net/test/read.cgi/tech/1054390397/

965 名前:デフォルトの名無しさん :04/04/11 16:28
template<typename T>struct deleter{void operator()(T *p){delete p;}};
const iterator mid = partition(v.begin(), v.end(), /* まだ必要 */);
for_each(mid, v.end(), deleter<void>());
v.erase(mid, v.end());

966 名前:デフォルトの名無しさん :04/04/11 16:30
>>956
>剽窃:他人の作品・学説などを自分のものとして発表すること。

つまり、初心者がどっかで書いてたものをぱくったって言いたいのかな?w

967 名前:デフォルトの名無しさん :04/04/11 17:15
>>965
必要かどうかの判定が *it ではなく it を使っているとしたら、そうはできないよね。

968 名前:デフォルトの名無しさん :04/04/11 20:42
標榜あたりと勘違い?

969 名前:デフォルトの名無しさん :04/04/11 21:59
>>968
「あたり」じゃなくて「そのもの」だと思われ。


970 名前:デフォルトの名無しさん :04/04/11 23:10
質問970:LPVOID*型を引数とする関数について

int func(LPVOID*) {

}
このようなLPVOID*型を引数にもち、そのポインタのポインタに
何らかの4バイトの結果を入れ、戻り値としてint型を返す関数が
あったとします。

LPVOID pbuf;
func((LPVOID*)&pbuf);//戻り値は無視する。

このように使えばその後で
wsprintf(buf, "%d", *(DWORD*)pbuf);
のようにして4バイトの値を得ることができました。

そこで、LPVOID pbuf;と宣言していたものを、LPDWORD pbuf;
とだけ変更してもうまくいきました。
DWORD *pbuf;とだけ変更した場合もうまくいきました。
DWORD pbuf[1];とだけ変更した場合もうまくいくと思ったのですが、
wsprintf(buf, "%d", *(DWORD*)pbuf);の結果が他の宣言の場合と
異なり、予想外だったのです。

func関数にはメモリの実体のポインタのポインタを指定すれば
いいようなんですが、なぜDWORD pbuf[1];とするとうまくいかなかった
のでしょうか?

971 名前:デフォルトの名無しさん :04/04/11 23:28
>>970
DWORD * pbuf;に対してのsizeof(pbuf)と、
DWORD pbuf[1];に対してのsizeof(pbuf)は
それぞれ幾つ?

972 名前:デフォルトの名無しさん :04/04/11 23:35
>>970
func(LPVOID* pp)は、*(DWORD *)pp = 値 みたいな書き換えをしてるんだよな?
つまり、呼出元が渡したポインタ自身を書き換えると。

で、DWORD pbuf[1]; して、それを func((LPVOID*)&pbuf);として、
funcがポインタのつもりで書き換えてるんだよな?
でもこの場合pbufはポインタではないので
(LPVOID*)&pbuf は、 ポインタではなく最初の要素のアドレスを返す)
この場合のみアドレスではなく要素を書き換えていることになる感じ。

ちなみにLPVOIDとかLPDWORDとかはC++ではなくMicrosoftなどの勝手typedefだし
c-style cast前提なのはC++ではなくCの流儀だな。

973 名前:デフォルトの名無しさん :04/04/11 23:41
>>971 ありがとうございます。

DWORD * pbuf;に対してのsizeof(pbuf)はポインタのサイズだから普通は4。
DWORD pbuf[1];に対してのsizeof(pbuf)もポインタのサイズだから普通は4。

これで間違いないでしょうか?


974 名前:デフォルトの名無しさん :04/04/11 23:43
>>973
>DWORD pbuf[1];に対してのsizeof(pbuf)もポインタのサイズだから普通は4。
違う。DWORD一個のサイズ。まあ4というのは一緒だがたまたまだな。
Win64なんかだとポインタのサイズは8だったり。

975 名前:デフォルトの名無しさん :04/04/12 00:04
なに的外れなことやってんの?

976 名前:デフォルトの名無しさん :04/04/12 00:18
Cスレ逝けば?

977 名前:デフォルトの名無しさん :04/04/14 14:03
誰だ名前空間なんて作ったのは。
おかげでバッティングだらけじゃないか。
なんでみんなstdなんだよヽ(`Д´)ノ

978 名前:デフォルトの名無しさん :04/04/14 15:46
>>977
なんだなんだ?using namespace std; 厨が暴れているぞ。

979 名前:デフォルトの名無しさん :04/04/14 17:45
>>978
ヘッダでやってるってことかしら。

980 名前:デフォルトの名無しさん :04/04/14 23:45
コンソール出力を同時にファイルへ書き出す方法ってありますか? C言語限定で。


981 名前:デフォルトの名無しさん :04/04/14 23:49
Cスレ逝けば?

982 名前:デフォルトの名無しさん :04/04/15 00:44
String s = "str1"+"str2";
みたいな書き方を実現する方法ってあるでしょうか?
String s = (String)"str1"+"str2";
しか思いつかないのです

983 名前:デフォルトの名無しさん :04/04/15 00:47
String s = "str1" "str2";

984 名前:デフォルトの名無しさん :04/04/15 01:03
>>983
右辺の型が任意の場合だと、キャストしかないですかね

985 名前:デフォルトの名無しさん :04/04/15 01:07
>>984
多分。
s += str2;でいいじゃん

986 名前:デフォルトの名無しさん :04/04/15 01:15
>>985
そのケースのみならそれでも良いのですが
どうもjavaの癖がついてしまっていろいろ面倒なのです。
スッキリしました。感謝。

987 名前:デフォルトの名無しさん :04/04/15 01:24
>>984
任意の型の文字列化にキャストって……どの程度一般的な型を想定してる?

もっと広範な用途で任意の型と文字列ベースのやり取りするなら std::stringstream が使える。
構文は不格好になるし牛刀な感じはあるが、標準ライブラリの範囲であれば他にない。

キャスト式で見た目きれいに書きたいのなら boost::lexical_cast 使ってみるのも。

988 名前:デフォルトの名無しさん :04/04/15 12:53
そろそろ次スレよろ。

989 名前:デフォルトの名無しさん :04/04/15 23:33
cppllとってる人っている?

990 名前:デフォルトの名無しさん :04/04/15 23:34
新聞かよ

991 名前:デフォルトの名無しさん :04/04/16 00:12
>>989
cppll読んでるけどしたらばのcppll BBSもなかなか面白い。

992 名前:デフォルトの名無しさん :04/04/16 00:32
>>989
俺にはレベルが高すぎてサパーリ


993 名前:デフォルトの名無しさん :04/04/16 00:37
>>989
アーカイブで読めるし無理に購読しようとは思わん。
下手に投稿しちゃうとスパム来るようになるし・・・

994 名前:デフォルトの名無しさん :04/04/16 01:07
>>993
それよりFree News ServerとかIEでftpやる時にメールアドレスが
まともに登録されているとスパムが来るようになる罠。

995 名前: ◆Manna2uCLg :04/04/16 01:36
次スレ立ててきまつ

996 名前: ◆Manna2uCLg :04/04/16 01:56
C++相談室 part29
http://pc5.2ch.net/test/read.cgi/tech/1082047479/l50

997 名前:デフォルトの名無しさん :04/04/16 02:19
comp.lang.c++.moderatedとかGotW読んでる人はいませんですかそうですか・・・

998 名前:デフォルトの名無しさん :04/04/16 02:49
そろそろ千取り合戦か…

999 名前:デフォルトの名無しさん :04/04/16 02:52
999

1000 名前:デフォルトの名無しさん :04/04/16 02:52
1000!!!!!!!!!!!!!!!


■過去ログ置き場に戻る■ 1- 前250 次250 最新50
DAT2HTML 0.33f Converted.