- PR -

Managed C++ != C++

投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2002-07-13 15:41
使っていて腹が立った
deleteできない!!、STL使えない、コピーコンストラクタ使えない、デフォルト引数使えない、etc...
これのどこがC++なんだよっ!!

もちろん回避方法はあります。__nogcって宣言してやればね。
こうすれば、deleteしなきゃいけないし、STLにも使えるし、
コピーコンストラクタも宣言できるし、デフォルト引数も使えるし・・・
そうすると、__nogcのクラスの中では__gcなクラスを引数として渡せなくなります。
また、__gcなクラスからは__nogcなクラスを継承できません。

Cの時代から「借りたものはきちんと返せ」を実践してきた身としては、
ガーベッジコレクションをしてくれる代わりに使えなくなる機能の方が魅力です。
それとも、「勝手に借りて放り出せ」という、最近の世情を反映しているのか。
うまいぞMS!?

さらに、「Visal Basic、Visual C#とのシームレスな開発環境」だって?!
VBからVC++は使えるが、VC++からVBは使えない(こと/ものもある)じゃん!!
クロスランゲージじゃなくて・・・バッテン!?

ほかにも、ダイアログ上で特定のコントロールの意味が知りたいのでF1を押したら・・・
どうしてダイアログのヘルプが開くわけ?
他のアプリは、そのコントロールのヘルプが開くじゃない。
ヘルプも貧弱になってるし。どうして「エラーの内容」しかなくて、
「修正方法」がないの!!これじゃ「ヘルプ」じゃなくて「辞書」じゃない!!

今まで「MSだからしゃ〜ないか」と思っていたけど、とうとう切れちゃいました。
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2002-07-14 22:32
なんかかなり無茶苦茶ですね。
とりあえず気になったところを書いておきます。

引用:

STL使えない


…これ、正直に意味がわからないのですが?

引用:

デフォルト引数使えない


これは正直私も賛成です。ただ、デフォルト引数を使ったメソッドを展開してくれればいいだけだと思うのに。
void foo(int a, int b=0);

void foo(int a, int b);
void foo(int a) { foo(a, 0); }
とすればいい。
ただ、少し複雑になる気もするので、仕方がないのかな、と。こう書けってことなんでしょうね。

引用:

そうすると、__nogcのクラスの中では__gcなクラスを引数として渡せなくなります。


…これも意味不明。

引用:

また、__gcなクラスからは__nogcなクラスを継承できません。


どんなに考えてもこれを可能とする手段が私は思いつきませんが。

引用:

Cの時代から「借りたものはきちんと返せ」を実践してきた身としては、
ガーベッジコレクションをしてくれる代わりに使えなくなる機能の方が魅力です。
それとも、「勝手に借りて放り出せ」という、最近の世情を反映しているのか。
うまいぞMS!?


…最近の世情になっているのは、それなりに理由があるのですが。直接的な問題解決としてはGCはメモリリークの解決ですね。私はGC以外に「どんなレベルの技術者が作ったとしても100%メモリリークを発生させない」方法を他に思いつきません。また、ユーザーが開放責任から開放された場合の生産性の向上は確かに無視できないレベルだと思います。
ただ、私はGCについては中立派です。GCが解決している事象に対して、少しGCというフレームワークが大きすぎるのではないか(またそれによって余計複雑になってしまったものもあるのではないか)と思うからです。しかし否定派ではないのは、GCよりもいいものが思いつかないからです。

引用:

さらに、「Visal Basic、Visual C#とのシームレスな開発環境」だって?!
VBからVC++は使えるが、VC++からVBは使えない(こと/ものもある)じゃん!!
クロスランゲージじゃなくて・・・バッテン!?


使えないものを具体的に教えていただきたいのですが。

引用:

ほかにも、ダイアログ上で特定のコントロールの意味が知りたいのでF1を押したら・・・
どうしてダイアログのヘルプが開くわけ?
他のアプリは、そのコントロールのヘルプが開くじゃない。
ヘルプも貧弱になってるし。どうして「エラーの内容」しかなくて、
「修正方法」がないの!!これじゃ「ヘルプ」じゃなくて「辞書」じゃない!!


…これは…言語ではなく、開発環境の問題ですね。


最後に私のMC++の現在の感想を書いておきます。
C++と.NETフレームワークがあまりにもなじまないため、はじめは「どうするんだろう?」と思っていました。そして、言語自体を変更するのではなく、拡張によって.NETの機能を実現している事がわかって、「なるほど。」と思いました(いや、まあ確かにそうするしかないのでしょうが)。
感じている利点としては、
「.NETに対応(当然.NETであるためにかなりの制限がつきます。もちろんプロパティ等の利点もつきますが)したコードと、今までのC++のコードが同じソースに共存できる。」

欠点は、
「生成、破棄に関して、旧C++クラスと、.NET C++クラスと二重の方法が存在する。これが生成破棄管理の複雑さを増す。」
「何よりもコードが美しくない。オペレータつくるのにop_Additionとかしないといけないのはなんとも…。プロパティもget_Foo()とかだし。」

結局総論としては、「.NETじゃ実現しにくいものをクラスライブラリとして使うのが一番だろう」って感じですかね…MC++にかぎって言えば。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2002-07-15 08:29
yaさん、どもです。
引用:

引用:

STL使えない


…これ、正直に意味がわからないのですが?


Standard Template Libralyが使えません。Managedではコピーコンストラクタが使えない(なぜ?)
ので、コピーコンストラクタを要求する一部のSTLコンテナが使えません。あった方がよいとされる
vectorやlistも、実際にはエラーになりました。


引用:

引用:

デフォルト引数使えない


これは正直私も賛成です。ただ、デフォルト引数を使ったメソッドを展開してくれればいいだけだと思うのに。
void foo(int a, int b=0);

void foo(int a, int b);
void foo(int a) { foo(a, 0); }
とすればいい。
ただ、少し複雑になる気もするので、仕方がないのかな、と。こう書けってことなんでしょうね。



おそらく、コピーコンストラクタが使えないことに起因すると思われます。その証拠に、
VBの方では使えています。VBでは実現方法が違うためでしょう。VC#でもOKじゃないかな?

引用:

引用:

そうすると、__nogcのクラスの中では__gcなクラスを引数として渡せなくなります。


…これも意味不明。



 腹立ったのでセーブしなかったのですが、エラーになりました。ほかのやり方があったの
かもしれませんが。

引用:

引用:

また、__gcなクラスからは__nogcなクラスを継承できません。


どんなに考えてもこれを可能とする手段が私は思いつきませんが。



 そうなんですけど・・・そうなんですけどね。「じゃぁ、__gcから継承したら暗黙で
__gcにしろよ」とも思います。キーワードを入れなければ「__gcから__nogcなクラスを
継承できません」というエラーになります。わざわざ__nogcなんて言うキーワードを作って
いるんだから暗黙で__gcにしろよ、っていうのはおかしいでしょうか。


引用:

引用:

Cの時代から「借りたものはきちんと返せ」を実践してきた身としては、
ガーベッジコレクションをしてくれる代わりに使えなくなる機能の方が魅力です。
それとも、「勝手に借りて放り出せ」という、最近の世情を反映しているのか。
うまいぞMS!?


…最近の世情になっているのは、それなりに理由があるのですが。直接的な問題解決としてはGCはメモリリークの解決ですね。私はGC以外に「どんなレベルの技術者が作ったとしても100%メモリリークを発生させない」方法を他に思いつきません。また、ユーザーが開放責任から開放された場合の生産性の向上は確かに無視できないレベルだと思います。
ただ、私はGCについては中立派です。GCが解決している事象に対して、少しGCというフレームワークが大きすぎるのではないか(またそれによって余計複雑になってしまったものもあるのではないか)と思うからです。しかし否定派ではないのは、GCよりもいいものが思いつかないからです。


 これは・・・!いや、最近の若者との対比です^^;。夜、駅前に行くと茶髪金髪の若者
がたむろし、翌朝は歩道中に弁当の空き容器が散乱している・・・
 ところで、GCは本当に正しく、“開発者”の意図通りに機能しているのでしょうか。
というのも、VBでは6以前でもガーベッジコレクションが行われるので解放しなくても
よい、というのは周知の事実ですが、使わなくなったポインタはNothingを参照させて、
使わないことを制御プログラムに教えてやらなくてはならないことも、“一部では”知ら
れた事実です。開発者はこの、「使わなくなったことを制御プログラムに教えてやる」こ
とをしなくてもよいのでしょうか。しなくてはいけないなら、解放するのも変わらないん
ですけどね。


引用:

引用:

さらに、「Visal Basic、Visual C#とのシームレスな開発環境」だって?!
VBからVC++は使えるが、VC++からVBは使えない(こと/ものもある)じゃん!!
クロスランゲージじゃなくて・・・バッテン!?


使えないものを具体的に教えていただきたいのですが。


 ウインドウズのフォームクラスが使えません。MSのニュースグループに投稿していま
すが、VBやVC#で言うところの、「System.Windows名前空間」が見えません。いまのところ。


引用:

「.NETに対応(当然.NETであるためにかなりの制限がつきます。もちろんプロパティ等の利点もつきますが)したコードと、今までのC++のコードが同じソースに共存できる。」


 これ、わかりません。そうできるんだろうと思っていたのですが・・・あ、いや、
引用:

欠点は、
「生成、破棄に関して、旧C++クラスと、.NET C++クラスと二重の方法が存在する。これが生成破棄管理の複雑さを増す。」


こっちが大きく感じているので、利点と感じられない、という方が正確でしょう。


引用:

結局総論としては、「.NETじゃ実現しにくいものをクラスライブラリとして使うのが一番だろう」って感じですかね…MC++にかぎって言えば。


そういう使い方をしたい・・・のですが、どうもう、こう、もやもやと・・・??
NothingBut.NETFX
大ベテラン
会議室デビュー日: 2001/09/13
投稿数: 102
投稿日時: 2002-07-15 10:54
引用:

Jittaさんの書き込み (2002-07-15 08:29) より:
Managedではコピーコンストラクタが使えない(なぜ?)


おっしゃっているのは__gcクラスのことだと思いますが、理由は__gcクラスは決して「値で」取られないからです。ポインタに対してコピーコンストラクタを発行するとスライシングが発生しますし、避けることができるにせよセマンティクス的にわかりやすくなるとは言えないでしょう。

ですが、__valueクラスは以下のように使えます。

コード:
__value struct V {
	public:
		int x;
};

void main() {
	V v;
	v.x = 2;
	V w;
	w = v;
	std::cout << w.x << std::endl;
	v.x = 100;
	std::cout << w.x << std::endl;
}


引用:

コピーコンストラクタを要求する一部のSTLコンテナが使えません。あった方がよいとされるvectorやlistも、実際にはエラーになりました。



gcrootはご覧になりましたか?

コード:
#using <mscorlib.dll>
#include <gcroot.h>
#include <iostream>
#include <vector>

__gc class C {
	public:
		int x;
};

void main() {
	gcroot<C*> gr;
	gr = new C();
	gr->x = 1;
	std::vector< gcroot<C*> > vec;
	vec.push_back(gr);
	gcroot<C*> h = vec.at(0);
	std::cout << gr->x << std::endl;
}


引用:

デフォルト引数使えない
これは正直私も賛成です。ただ、デフォルト引数を使ったメソッドを展開してくれればいいだけだと思うのに。
void foo(int a, int b=0);

void foo(int a, int b);
void foo(int a) { foo(a, 0); }
とすればいい。
ただ、少し複雑になる気もするので、仕方がないのかな、と。こう書けってことなんでしょうね。


オーバーローディングとの兼ね合いの問題もある気がします。ちなみにこれはC#でもできません。VB.NETではOptional引数で可能です。ちなみに、C#/C++とVB.NETではオーバーロード解決の規則が異なります。

引用:

そうすると、__nogcのクラスの中では__gcなクラスを引数として渡せなくなります。


__valueまたはgcrootを参照してください。

引用:

「じゃぁ、__gcから継承したら暗黙で__gcにしろよ」とも思います。キーワードを入れなければ「__gcから__nogcなクラスを継承できません」というエラーになります。わざわざ__nogcなんて言うキーワードを作っているんだから暗黙で__gcにしろよ、っていうのはおかしいでしょうか。


私見ですが、コードの可読性は損なわれると思います。

引用:

というのも、VBでは6以前でもガーベッジコレクションが行われるので解放しなくてもよい、というのは周知の事実ですが、使わなくなったポインタはNothingを参照させて、使わないことを制御プログラムに教えてやらなくてはならないことも、“一部では”知られた事実です。


本当ですか?スコープを抜けても「Nothing化」(<-なににNothingを代入しているかによって意味はまったく異なります)されないとしたらVBランタイムのバグってことだと思いますが。もし手近な例があるようでしたらぜひお教えください。

引用:

ウインドウズのフォームクラスが使えません。MSのニュースグループに投稿していますが、VBやVC#で言うところの、「System.Windows名前空間」が見えません。いまのところ。


コード:
#define VC_EXTRALEAN
#include <afxwin.h>
#using <mscorlib.dll>
#using <system.dll>
#using <system.windows.forms.dll>

__gc class form1 : public System::Windows::Forms::Form {
protected:
	System::Windows::Forms::Button *btn;
public:
	form1() {
		btn = new System::Windows::Forms::Button();
		btn->Click += new System::EventHandler(this, &form1::click);
		Controls->Add(btn);
	}
	void click(System::Object sender, System::EventArgs e) {
		AfxMessageBox("MFC is here to stay!");
	}
};

int main() {
   System::Windows::Forms::Application::Run(new form1());
   return 0;
}
//cl /clr form.cpp /link /subsystem:windows /entry:main

Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2002-07-15 12:52
NothingBut.NETFXさん、こんにちは。

__value, gcroot 、じっくり見ます。


引用:

引用:

というのも、VBでは6以前でもガーベッジコレクションが行われるので解放しなくてもよい、というのは周知の事実ですが、使わなくなったポインタはNothingを参照させて、使わないことを制御プログラムに教えてやらなくてはならないことも、“一部では”知られた事実です。


本当ですか?スコープを抜けても「Nothing化」(<-なににNothingを代入しているかによって意味はまったく異なります)されないとしたらVBランタイムのバグってことだと思いますが。もし手近な例があるようでしたらぜひお教えください。



 本当です。前の会社で、そのためにメモリをどんどん食いつぶされ、苦労している人が今した。PGは見ていませんが、NTのタスクマネージャで、メモリ使用量がどんどん増えているのは見せてもらいました。私自身はVB使いではないので、その人から聞いた話でしかありませんが。あとから、「参照を解除せんと(Nothigを代入しないと)あかんかった」と聞きました。

 ウインドウズフォームの件、ありがとうございます。いったいどこに書いてあるのでしょう?要は「#using」句の部分ですよね。ヘルプからMSのサポート情報から、思いつく限りの文字列を放り込んで検索してみたんですけど・・・
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2002-07-15 22:02
ほとんど解説されちゃってますなぁ…。
とりあえずヘルプの位置。
Microsoft Visual Studio .NETドキュメントのなかの「Visual C++」-「C++マネージ拡張プログラミング」のなかにだいたいの資料はあります。
特に、「C++マネージ拡張リファレンス」や「C++マネージ拡張仕様」が参考になると思います。ただ、これが本当に不思議なのですが、「C++マネージ拡張仕様」のほうは、そのトップページからのリンクはなくて、横のツリーから読みたいものを選択する必要があります。

ただ、私としても、あまりに文献が少ないので、手探りでやっているところですね。「#using」節もサンプルから知りましたし。

引用:

じゃぁ、__gcから継承したら暗黙で __gcにしろよ」


これは私も反対です。そのクラスだけを見たときに、__gcクラスなのか、__nogcクラスなのかわかんなくなっちゃいます。

ちなみにGCの是非について。繰り返しますが、私は中立派です。「強い参照を解除しなくては開放されない」のは本当ですし。もちろん、参照を解除すればかってに開放してくれるわけですが、直接的な開放ではないので、少しわかりにくい気もするし…。
また、ガベージコレクタのスレッドが別スレッドになってしまうため、開放にはそれも考慮しなくてはなりません。必然的にマルチスレッドプログラムの知識が要求されます。
開放責任からの完全開放が不可能なものについてはIDisposableインターフェイスとか、確かに色々と工夫はあります。ただ、複雑化している部分もある気がします。
色々と文句は出るんですが、逆に「いいなぁ」って所も多いんですよ。正直、「すべての」オブジェクトに対して、開放責任を考えるのはめんどくさいです。これは直接的に生産性の低さにも繋がります。C#をはじめて使ったときには、生産性の高さに少し驚きました。開放責任からの開放は、「メモリリークを起こらなくする」ことよりもこの「生産性の向上」のほうが重要な気もします。

結局、GCにも利点と欠点があるだけです。いかにも革新的で今までの明示的な生成開放よりすべてにおいていいものみたいに言われてますが、そうではないと思います。
NothingButXMLInfoSet
大ベテラン
会議室デビュー日: 2002/07/16
投稿数: 116
投稿日時: 2002-07-16 01:33
...「解放」ですね。

引用:

yaさんの書き込み (2002-07-15 22:02) より:
「強い参照を解除しなくては開放されない」のは本当ですし。もちろん、参照を解除すればかってに開放してくれるわけですが、直接的な開放ではないので、少しわかりにくい気もするし…。


参照を解除することと、リソースを解放することとは、していることがまったく異なるわけですから、両者が分けられていて別々に扱わなければならないのは当然だと思います。

引用:

また、ガベージコレクタのスレッドが別スレッドになってしまうため、開放にはそれも考慮しなくてはなりません。必然的にマルチスレッドプログラムの知識が要求されます。


無理やりTLSでも使わない限り、GCとマルチスレッディングは関係ないと思っていいと思います。当然ですが、GCと通常処理とでレースコンディションが発生することなどはないので。

引用:

開放責任からの完全開放が不可能なものについてはIDisposableインターフェイスとか、確かに色々と工夫はあります。ただ、複雑化している部分もある気がします。


たぶん従来のC++ユーザーのデストラクションへの欲求を満たすためなのだとは思いますが、IDisposableは過度に宣伝されすぎだと思います。IDisposableを必要とするクラスをこれから自前で設計することなどほとんどないし、リソースの厳密な管理が必要なクラスが万が一出てきたら、IDisposableなんぞでは管理できないことのほうが多そうですし。

引用:

結局、GCにも利点と欠点があるだけです。いかにも革新的で今までの明示的な生成開放よりすべてにおいていいものみたいに言われてますが、そうではないと思います。


すべてにおいていいと言い切れるほどの知識は持っていませんが、やはりGCのほうが、人間が明示的にやるよりも効率性や完全性の面でも有利だと思います。プログラミングの段階では解放可能なタイミングがわからないことも多いので。

GCやJITterは、プログラマが持ち得ない実行時の情報を持っています。この点について、プログラマは逆立ちしてもかないません。
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2002-07-16 06:40
解放の字…間違ってましたね、すいません。

引用:

無理やりTLSでも使わない限り、GCとマルチスレッディングは関係ないと思っていいと思います。当然ですが、GCと通常処理とでレースコンディションが発生することなどはないので。


C++で、「シングルスレッド実行のみ」を考えて作ったSoundクラスです。

class Sound
{
private:
 set<Sound*> Instances;
public:
 Sound(){ Instances.insert(this); }
 virtual ~Sound(){ Instances.erase(this); }

 void Play(){ ... }

 static void PlayAll(){
  set<Sound*>::iterator p = Instances.begin();
  for(; p!=Instances.end() ; p++) { p->Play(); }
 }
};

ちなみにマルチスレッド対応にするには、WindowsではCreticalSectionなどを使ったクラスを作って、同時にInstancesにアクセスしないようにすればいいだけです。ただし、このクラスでもほとんどの場合十分です。
ただし、これをC#にしようとすると、ファイナライザが別スレッドで実行される可能性がある、またはファイナライザの実行タイミングがわからないため、マルチスレッド対策が必須になってしまいます。もし、PlayAllを呼び出しているときにGCが発動すると、ファイナライザ終了後に現在の列挙が有効ではなくなっておそらくExceptionが発生するでしょう。
これは一例ですが、少なくとも、「マルチスレッド実行の強制」である以上、こういう問題は出てきます。本来ならばマルチスレッドにするまでもないプログラムまで、考える必要がでてくるという事です。

引用:

たぶん従来のC++ユーザーのデストラクションへの欲求を満たすためなのだとは思いますが、IDisposableは過度に宣伝されすぎだと思います。IDisposableを必要とするクラスをこれから自前で設計することなどほとんどないし、リソースの厳密な管理が必要なクラスが万が一出てきたら、IDisposableなんぞでは管理できないことのほうが多そうですし。


ユーザーの解放責任の完全開放が出来ないものがある限り、解放するための共通手段、つまりインターフェイスを用意したのは必然だと思います。それと、「IDisposableなんぞでは管理できないことのほうが多そうですし」というのがいまいちわかりません。

引用:

すべてにおいていいと言い切れるほどの知識は持っていませんが、やはりGCのほうが、人間が明示的にやるよりも効率性や完全性の面でも有利だと思います。プログラミングの段階では解放可能なタイミングがわからないことも多いので。


有利な面がなければそもそもGCなんて生まれないと思います。そしてその利点が有効でなければここまで広がりません。だから私は「否定」はしていません。

引用:

GCやJITterは、プログラマが持ち得ない実行時の情報を持っています。この点について、プログラマは逆立ちしてもかないません。


持ち得ないというのは微妙ですね。まあ、それと「簡単にできるか」というものは別問題なので、否定はしませんが。


…何か話がスレッドとずれてきているような気もします。GCの議論の別スレッドをつくった方が良いかもしれません。

スキルアップ/キャリアアップ(JOB@IT)