this修飾子とclass:: 修飾子との違いは?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
さば

this修飾子とclass:: 修飾子との違いは?

#1

投稿記事 by さば » 18年前

例えば、

calss A{
short s;
....

}

A::A(short s){ // class Aのコンストラクタ
A::s = s; // ------① class Aのコンストラクタの引数をclass Aのメンバーに代入したい。
this->s = s; // ------② class Aのコンストラクタの引数をclass Aのメンバーに代入したい。
}

MS VC2005の場合、両方ともコンパイルできたのですが、
以前から大原則として、コンストラクタの中に"this"を使ってはいけないという記憶を持っていて、
ずーと守ってきました。

それでは
Q1. A::s と this->s とは何が違うのでしょうか?
Q2. コンストラクタの中に"this"を使ってはいけないという大原則はもう敗れてもいい時代になっているのでしょうか?


おしえていただけませんでしょうか。

さば

Re:this修飾子とclass:: 修飾子との違いは?

#2

投稿記事 by さば » 18年前

すみません。

訂正:
[誤]敗れてもいい...
[正]破ってもいい...

たかぎ

Re:this修飾子とclass:: 修飾子との違いは?

#3

投稿記事 by たかぎ » 18年前

> 以前から大原則として、コンストラクタの中に"this"を使ってはいけないという記憶を持っていて、

その記憶の出所はどこでしょうか?
私が知る限り、そんな原則は存在しません。

さば

Re:this修飾子とclass:: 修飾子との違いは?

#4

投稿記事 by さば » 18年前

> その記憶の出所はどこでしょうか?
> 私が知る限り、そんな原則は存在しません。

私の理解ではコンストラクタの時点ではthis(classのobject)がまだ生成されてないため、使えないわけですけれども。
これは私の想像ではないと思います。

たかぎ

Re:this修飾子とclass:: 修飾子との違いは?

#5

投稿記事 by たかぎ » 18年前

> 私の理解ではコンストラクタの時点ではthis(classのobject)がまだ生成されてないため、使えないわけですけれども。

その情報の出所を知りたいですね。

ISO/IEC 14882:2003の9.3.1 Nonstatic member functionsから引用すると、

When an id-expression (5.1) that is not part of a class member access syntax (5.2.5) and not used to form a
pointer to member (5.3.1) is used in the body of a nonstatic member function of class X or used in the
mem-initializer for a constructor of class X, if name lookup (3.4.1) resolves the name in the id-expression to
a nonstatic nontype member of class X or of a base class of X, the id-expression is transformed into a class
member access expression (5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of the .
operator.

とあり、(コンストラクタを含む)非静的メンバ関数の中で、クラスメンバアクセス構文を使わずに直接メンバを触る場合は、(*this).メンバ と書くのと同じことになります。
つまり、明示的に this を書く書かないに関わらず、this が使われることになるわけです。

バグ

Re:this修飾子とclass:: 修飾子との違いは?

#6

投稿記事 by バグ » 18年前

私は、コンストラクタでメンバの初期化処理をしたりしてますが、さばさんの理屈でいくと…コンストラクタが呼ばれた時点でオブジェクトが存在してないという事は、コンストラクタの中では何もできない事になってしまいませんか?

管理人

Re:this修飾子とclass:: 修飾子との違いは?

#7

投稿記事 by 管理人 » 18年前

このトピにおける投稿に一部規約に違反した文章がありましたので、複数修正いたしました。
またこの掲示板はトップにあります「規約」に準じています。
他にも禁止行為が残っていますので規約を良くお読みになり、禁止行為や義務行為については規約を守った投稿をお願いします。

さば

Re:this修飾子とclass:: 修飾子との違いは?

#8

投稿記事 by さば » 18年前

たかぎ様、バグ様
ご返事有難う御座います。

たかぎ様の文章はとても説得力ありますね。
でも、コンストラクタの中にthisを使ってはいけない記憶も強くて、
大変申し訳御座いませんが、すぐ根拠を出せと言われても出せないんですが、
可能性のあるところを挙げますと
1.MS VC6.0か
2.詳解 C++ 雑誌ではないですけど C MAGAZINE ----ソフトバンク出版
3.解明 C++ ???

いずれも自分が所有する本ではないので、詳しくいえないのです。

ただ、これから調べるつもりです。

管理人さんへ:
お世話になっております。

>このトピにおける投稿に一部規約に違反した文章がありましたので、複数修正いたしました。
これから避けるために
1."一部規約に違反した文章"について一つでも具体的なところをご説明いただけませんか。
2."複数修正いたしました" どんな処でしょうか。

どうぞ宜しくお願いします

管理人

Re:this修飾子とclass:: 修飾子との違いは?

#9

投稿記事 by 管理人 » 18年前

違反した箇所についてやその他投稿者様の個人情報について公の場で公言しないと規約に書きましたので、具体的な部分についてはメールでお答えいたします。
よろしければ
dixqhp@gmail.com
宛てにメールをお送り下さい。

なぎ

Re:this修飾子とclass:: 修飾子との違いは?

#10

投稿記事 by なぎ » 18年前

コンストラクタの中では、オブジェクトの生成は*完了していない*のは確かです。
ただし、this は、コンストラクタに入った時点では存在しています。

コンストラクタの入り口では、少なくとも、将来オブジェクトになるはずの領域だけは確保されていて、その後で、いわゆる初期化が行われて、オブジェクトの生成が完了することになります。

この点が話題になるのは、コンストラクタ内で例外をスルーできるかどうかというようなことですね。
例外がスルーされると、「構築の完了したオブジェクト」は暗黙のうちにデストラクトされるわけですが、コンストラクタ内で例外がスルーされると、未構築のオブジェクトが残骸となって残ってしまうというわけです。

たかぎ

Re:this修飾子とclass:: 修飾子との違いは?

#11

投稿記事 by たかぎ » 18年前

コンストラクタからの例外送出に関しては、(手前味噌ですが)下記で解説しています。
http://www.kijineko.co.jp/tech/supersti ... uctor.html

さば

Re:this修飾子とclass:: 修飾子との違いは?(さすが! お礼)

#12

投稿記事 by さば » 18年前

たかぎ様に膝まずくしかできない!

「生成は完了していない」という記憶と「コンストラクタ内で例外をスルーできない」
記憶の間から、なんと「this」を使ってはいけないという"記憶"が生まれてしまいました。
そしてずーと守ってきたのです!


>この点が話題になるのは、コンストラクタ内で例外をスルーできるかどうかというようなことですね。
>例外がスルーされると、「構築の完了したオブジェクト」は暗黙のうちにデストラクトされるわけですが、コ>ンストラクタ内で例外がスルーされると、未構築のオブジェクトが残骸となって残ってしまうというわけです。

!!!

ほんとうにいい勉強になりました。

たかぎ

コンストラクタからの例外送出

#13

投稿記事 by たかぎ » 18年前

もしかすると誤解があるといけませんので念のため。

コンストラクタの中でエラーが発生した場合は、例外を送出することで外部に通知<u>すべき</u>です。

先に紹介したリンク先でも解説していますが、コンストラクタが失敗したということは、そのオブジェクトは未生成です。
オブジェクトの中に状態フラグのようなものを持たせたとしても、未生成のオブジェクトを操作して、フラグの値を参照するのはナンセンスだからです。

さば

Re:コンストラクタからの例外送出(あっ、そう言えば)

#14

投稿記事 by さば » 18年前

たかぎ 様
ご教授本当に有難うございます。

この前頂いたページの中に以下のような事が書かれております。
1. ★「オブジェクトの生存期間というのは、コンストラクタの処理が完了した時点から始まります。
生まれていないものが(デストラクタによって)死ぬことはナンセンスですし、生まれていないものに対して、
何らかの操作を行うのも同じくナンセンスです。」

この文脈からしますと、やはり、コンストラクタの処理が完成していない時に、
object(classのinstance)が生成されていないようですね。
Q1. にも関わらず、 objectを指すpointerが先行して生成されるのでしょうか。

2.★「また、コンストラクタが失敗したことを通知する一般的な手段は例外しかありません。」
Q2. これも"コンストラクタ内で例外をスルーできない"に矛盾するような感じですね

実際、私が作ったclassのコンストラクタの中で結構いろいろな処理をやっています。
例外や失敗を発生する可能性は十分あります。

Q3.コンストラクタの中で発生した例外や失敗をどうやってclassの生成側に知らせるのでしょうか
(コンストラクタにはreturn値を持たないですね)

また宜しくお願い申し上げます

たかぎ

Re:コンストラクタからの例外送出(あっ、そう言えば)

#15

投稿記事 by たかぎ » 18年前

> Q1. にも関わらず、 objectを指すpointerが先行して生成されるのでしょうか。

生成が完了していないことと、それを指すポインタが利用できるかどうかは話が別です。
何らかの方法で生成しようとしているオブジェクトにアクセスできなければ、生成そのものができません。

> Q2. これも"コンストラクタ内で例外をスルーできない"に矛盾するような感じですね

ですから、コンストラクタから例外は送出<u>できる</u>のです。

> Q3.コンストラクタの中で発生した例外や失敗をどうやってclassの生成側に知らせるのでしょうか
> (コンストラクタにはreturn値を持たないですね)

例外を送出することで通知します。

さば

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#16

投稿記事 by さば » 18年前

たかぎ様が言われた「送出」ということは「スルー」ではないですね?
私は「スルー」として理解していますが。


また宜しくお願い申し上げます。

YuO

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#17

投稿記事 by YuO » 18年前

> たかぎ様が言われた「送出」ということは「スルー」ではないですね?
> 私は「スルー」として理解していますが。

スルーとは?
たかぎさんの言われる「送出」とは,例外をthrowすることだと思います。
ISO/IEC 14882の「throw」に相当する部分はJIS X 3014でも「送出」を使っているので,間違いないでしょう。

逆に,例外を「スルー」するという表現は初めて見ました。

ちなみに,throwはカタカナで書くなら通常「スロー」です。

たかぎ

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#18

投稿記事 by たかぎ » 18年前

> たかぎさんの言われる「送出」とは,例外をthrowすることだと思います。
> ISO/IEC 14882の「throw」に相当する部分はJIS X 3014でも「送出」を使っているので,間違いないでしょう。

はい、そのとおりです。

たかぎ

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#19

投稿記事 by たかぎ » 18年前

> 逆に,例外を「スルー」するという表現は初めて見ました。

私は throw の意味だと解釈していましたが、もしかすると例外を catch せずに through するという意味だったのかもしれませんね。
A::A()
{
  func();  // ← ここで発生した例外を catch せず、呼び出し元にそのまま伝播するという意味?
}
 

さば

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#20

投稿記事 by さば » 18年前

>たかぎさんの言われる「送出」とは,例外をthrowすることだと思います。
私もそういうふうに理解していました。
そうしますと、
「コンストラクタ内で例外がスルーされると、未構築のオブジェクトが残骸となって残ってしまうというわけです。 (さば注:後にリークになりかねます)」という説もありまして、結局、コンストラクタ内で例外がスルー(= throw = 送出)はいけないことになるのでは、という質問になりますね。

私の誤解かもしれませんが、またご指導お願い致します。

たかぎ

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#21

投稿記事 by たかぎ » 18年前

> 「コンストラクタ内で例外がスルーされると、未構築のオブジェクトが残骸となって残ってしまうというわけです。 (さば注:後にリークになりかねます)」という説もありまして、結局、コンストラクタ内で例外がスルー(= throw = 送出)はいけないことになるのでは、という質問になりますね。

リークするから例外を送出してはいけないのではなく、例外が送出されてもリークが起こらないように実装しなければならないのです。
また、下手糞な設計やコーディングによってリークが発生するのは、何もコンストラクタに限ったことではありません。

GPGA

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#22

投稿記事 by GPGA » 18年前

コンストラクタ内で、エラーが発生した際に、リークが起こらないようにし
さらに例外を送出するというのは以下のようなことですか?
#include <iostream>

class A
{
public :
    A() {
        p1 = NULL;
        p2 = NULL;
        p1 = new unsigned int[1024 * 1024];
        //if (p1 == NULL) { //本当はこちらが正しいが、あえてエラーということにさせる
        if (p1 != NULL) {
            goto err;
        }
        p2 = new unsigned int[1024 * 1024];
        if (p2 == NULL) {
            goto err;
        }
        return ;

err :
        delete[/url] p2;
        delete[/url] p1;
        throw "out of memory";
        return ;
    }
    ~A() {
        delete[/url] p2;
        delete[/url] p1;
    }
private :
    unsigned int* p1;
    unsigned int* p2;
};

int main()
{
    try {
        A* a = new A();
        delete a;
    } catch (const char* p) {
        std::cout << p << std::endl;
    }
    return 0;
}
 

さば

Re:コンストラクタからの例外送出(なるほど!)

#23

投稿記事 by さば » 18年前

たかぎ様
良く分かりました。

>リークするから例外を送出してはいけないのではなく、例外が送出されてもリークが起こらないように実装しなければならないのです。
>また、下手糞な設計やコーディングによってリークが発生するのは、何もコンストラクタに限ったことではありません。

そういう意味ですね!

ほんとうに有難うございます。
また宜しくお願い致します。

たかぎ

Re:コンストラクタからの例外送出(一点だけご確認させてください)

#24

投稿記事 by たかぎ » 18年前

> コンストラクタ内で、エラーが発生した際に、リークが起こらないようにし
> さらに例外を送出するというのは以下のようなことですか?

いいえ。
new 式が失敗した場合は、NULL を返すのではなく、std::bad_alloc が例外として送出されます。
ですから、そのコードではリークが発生してしまいます。
以下のようにすることで、リークは回避できます。
A::A()
try
  : p1(0), p2(0)
{
  p1 = new unsigned int[1024*1024];
  p2 = new unsigned int[1024*1024];
}
catch (...)
{
  delete[/url] p1;
  delete[/url] p2;
  throw;
}
あるいは、
class A
{
public:
  A() : v1(1024*1024, 0), v2(1024*1024, 0) {}
private:
  std::vector<unsigned int> v1;
  std::vector<unsigned int> v2;
};
のようにしてもよいでしょう。

GPGA

Re:コンストラクタからの例外送出(なるほど!)

#25

投稿記事 by GPGA » 18年前

現行のコンパイラで考えると戻り値のNULLチェックより
例外のbad_allocのほうが、もう主流ですかね?
#include <iostream>

class A
{
public :
    A() {
        p1 = NULL;
        p2 = NULL;
        try {
            p1 = new unsigned int[1024 * 1024];
            p2 = new unsigned int[1024 * 1024];
        } catch (std::bad_alloc) {
            delete[/url] p2;
            delete[/url] p1;
            throw "out of memory";
        }
    }
    ~A() {
        delete[/url] p2;
        delete[/url] p1;
    }
private :
    unsigned int* p1;
    unsigned int* p2;
};

int main()
{
    try {
        A* a = new A();
        delete a;
    } catch (const char* p) {
        std::cout << p << std::endl;
    }
    return 0;
}
 

さば

Re:コンストラクタからの例外送出(なるほど!)

#26

投稿記事 by さば » 18年前

GPGA様へ
GPGA様のご返答を見逃したので申し訳ございませんでした!

丁寧な実例コードありがとうございます。
面白い例ですね。どうなるのでしょうか。
経験からしますと、

delete[/url] p2;
この文にる例外が先に起こって

delete[/url] p1; と
throw "out of memory";
が実行されないはずです。

ややこしいC言語ですね。
一歩間違えば地獄!
例えば、
銀行業なんかC(C++)で開発する場合、想像だけでも背筋にびりっと寒気が走るほど、、、

また宜しくお願い致します。

さば

Re:コンストラクタからの例外送出(なるほど!)

#27

投稿記事 by さば » 18年前

試しに回答します。

sp = new (nothrow) short[100];
にすれば、メモリ確保失敗の場合、NULLを返します。
さもなければ、throwが起きます。

【どっちが主流になるべきかについて私は回答できませんが】


また宜しくお願い致します

たかぎ

Re:コンストラクタからの例外送出(なるほど!)

#28

投稿記事 by たかぎ » 18年前

> 現行のコンパイラで考えると戻り値のNULLチェックより
> 例外のbad_allocのほうが、もう主流ですかね?

組込み向けのものを除けば、new 式が失敗したときに NULL を返す処理系はもうないと思います。
(NULL を返したいのであれば、std::nothrow を引数として渡す必要があります。)

> delete[/url] p2;
> この文にる例外が先に起こって

これはなぜでしょう?
delete 演算子が例外を送出することはありませんし、デストラクタは決して例外を送出してはなりません。

> ややこしいC言語ですね。

C++ですね。

> 一歩間違えば地獄!

C/C++では、いい加減なコーディングを行って、動かしてみてバグを見つけるというのは駄目です。
地獄に落ちない設計を行い、道を誤りそうになってもすぐにそれを検出できるように、いろいろ仕掛けをしておく必要がありますね。

GPGA

Re:コンストラクタからの例外送出(なるほど!)

#29

投稿記事 by GPGA » 18年前

> たかぎさん
すいません、かぶってしまいました。

>new 式が失敗した場合は、NULL を返すのではなく、std::bad_alloc が例外として送出されます。
>ですから、そのコードではリークが発生してしまいます。
私が保持しているEfective C++の第二版(もう第三版が出てますが)には、新しいコンパイラでも必要であると
判断されたのであれば NULL を返すと記載されていました。もっともこの第二版が出たのは9年も昔なので
あまり当てにできませんが。
返答内容を確認させていただきますと、やはりbad_allocで例外をキャッチするのが当たり前と考えてよさそうですね。

その他コンストラクタの初期化の前に tryを挟むことができることは、初めて知りました。
勉強させていただきました。

二番目に提示していただいた、vectorクラスを使用している部分ですが、テンプレートの第二引数は
確か、標準でstd::allocatorが代入されていたと思うのですが
これをはずすことにどのような意味があるのでしょうか?


>さばさん
最初の提示したコードに関しては、たかぎさんがおっしゃるとおり、bad_allocが例外として投げられ
それが、main内での try~catch に引っかかるため問題がメモリが開放されずにリークが発生いたします。
2番目に提示したコードでは、たかぎさんからご指摘のあったbad_allocで例外を取得して処理をしています。
ここでキャッチした後のdelete[/url]文についてですが、C++の規格では、deleteおよび、delete[/url]の対象が
NULLであった場合、deleteおよび、delete[/url]は何も処理を行わないというのが決められていたと思います。
コンストラクタの最初で P2にNULLを代入していますので、delete[/url] p2; で問題が発生することはないと思います。

たかぎ

Re:コンストラクタからの例外送出(なるほど!)

#30

投稿記事 by たかぎ » 18年前

> Efective C++の第二版

第二版の内容はすでに時代遅れになっている部分も多いですね。第三版では、例外安全に関する記述もかなり含まれていたように記憶しています。(例外安全に関しては Exceptinal C++ の方が詳しいですし、分かりやすいかと思います。)

> 二番目に提示していただいた、vectorクラスを使用している部分ですが、テンプレートの第二引数は
> 確か、標準でstd::allocatorが代入されていたと思うのですが
> これをはずすことにどのような意味があるのでしょうか?

今回使用している std::vector のコンストラクタは
template<class InputIterator>
  vector(InputIterator first, InputIterator last, const Allocator& a = Allocator());
です。これは本来反復子を渡すためのものですが、実引数の型次第では、
explicit vector(size_type n, const value_type& value = T(),
                             const Allocator& a = Allocator());
を呼び出したのと同じ意味になります。

さば

Re:コンストラクタからの例外送出

#31

投稿記事 by さば » 18年前

経験談ですけれども、
NULLポインタに対するdelete[/url]は決して何もしないわけではないようです。
すぐにはthrowしないかもしれませんが、その直後(どの時点については言えませんが)
必ずメモリエラー出ます(プログラムが強制中止されます)
これはVC6.0の時代でも VC2005の時代でも変わらないと思います。
皆さん経験されていません?

tk-xleader

Re:コンストラクタからの例外送出

#32

投稿記事 by tk-xleader » 18年前

>NULLポインタに対するdelete[/url]は決して何もしないわけではないようです。
>すぐにはthrowしないかもしれませんが、その直後(どの時点については言えませんが)
>必ずメモリエラー出ます(プログラムが強制中止されます)


それ本当ですか。free(NULL)の場合は何も起きないのはANSI規格で定められていますけど。

GPGA

Re:コンストラクタからの例外送出

#33

投稿記事 by GPGA » 18年前

>Exceptinal C++
まだ呼んだことがなかったので早速アマゾンで購入してみました。


>> 二番目に提示していただいた、vectorクラスを使用している部分ですが、テンプレートの第二引数は
>> 確か、標準でstd::allocatorが代入されていたと思うのですが
>> これをはずすことにどのような意味があるのでしょうか?
ここの私の発言はテンプレートとコンストラクタをごちゃ混ぜにしていますね。
後から見て自分でも何を言っているのかわからなかったです。。。


>今回使用している std:vector のコンストラクタは
>template<class InputIterator>
> vector(InputIterator first, InputIterator last, const Allocator& a = Allocator());
このコンストラクタは始めて見ました。
イテレータを扱えるコンストラクタがあったのですね。

たかぎ

Re:コンストラクタからの例外送出

#34

投稿記事 by たかぎ » 18年前

> NULLポインタに対するdelete[/url]は決して何もしないわけではないようです。
> すぐにはthrowしないかもしれませんが、その直後(どの時点については言えませんが)
> 必ずメモリエラー出ます(プログラムが強制中止されます)

ISO/IEC 14882:2003の5.3.5 Deleteの段落2に

if the value of the operand of delete is the null pointer the operation
has no effect.

とありますから、少なくとも標準規格では、delete[/url] NULL; は何も行いません。

たかぎ

Re:コンストラクタからの例外送出

#35

投稿記事 by たかぎ » 18年前

> >Exceptinal C++
> まだ呼んだことがなかったので早速アマゾンで購入してみました。

素早いですね。
この本はかなりレベルが高いので、もしかすると読み進めるのにかなり時間がかかるかもしれません。
それでも、一通り読破すれば、C++に関する知識は格段に深まるはずです。

tk-xleader

Re:コンストラクタからの例外送出

#36

投稿記事 by tk-xleader » 18年前

そうですか、ならばdeleteやdelete[/url]のあとにNULL代入という技が使えるわけですね。
あるコーディングに関する本に載っていましたので。

さば

Re:コンストラクタからの例外送出(自分もショックな感想)

#37

投稿記事 by さば » 18年前

本当にいい勉強になりました。

【以下は自分の苦悩を述べているだけで、CやC++のファインに対する否定ではないです。
[C++やCの歴史的な位置も知っているつもりですけれども]
------技術的な視点からのご批判を期待致します】

A. C(C++)の場合、アルゴリズム以外、言語自身について(センテンスエラーレベルでなくて)
いろいろ考えなければ危険が満ちています。
それに、長い間やってもやはりはっきりしないところ多いです。 (言語自身の変化やバージョンも多い)

B. 各プログラマが言語自身のためのあらゆる安全策を講じることは、
負担が多すぎではないかと思います。

C. 仮に立派な仕組み(メモリの自動的な安全管理、例外発生する時のstack的なメッセージ表示など)を独自で構築できても、所詮Java言語になるのではないでしょうか!?

D. Javaなら、OSでさえ意識しなくてもいいような感じですね------工学や科学領域の処理内容(アルゴリズム)の多くはそもそもOSに依存すべきではないですから。

E. 銀行業なら、Javaを選択するのは賢明に思います。

F. OSやハードを制御するにのみ、(C)C++の強みでしょう。

G. CやC++にある程度経験を持っているつもりだが、やはり完敗! そして無残に!

たかぎ

Re:コンストラクタからの例外送出(自分もショックな感想)

#38

投稿記事 by たかぎ » 18年前

> A. C(C++)の場合、アルゴリズム以外、言語自身について(センテンスエラーレベルでなくて)
> いろいろ考えなければ危険が満ちています。

これは、その通りです。

> それに、長い間やってもやはりはっきりしないところ多いです。 (言語自身の変化やバージョンも多い)

標準規格をよりどころにすることで、かなりすっきりすると思います。
言語自身の変化という意味では、10年前以上前ならともかく、現在では非常に安定しています。(処理系の標準準拠度の問題が残ってはいますが)
少なくとも、Java や C# よりはずっと安定しています。

> B. 各プログラマが言語自身のためのあらゆる安全策を講じることは、
> 負担が多すぎではないかと思います。

C/C++は、半日~数日程度勉強して、後はリファレンスを見ながら何とかする類の言語ではありません。
いちいち考えながらプログラミングしていたのでは非常に効率が悪いので、安全策に関してはある程度体で覚えることが必須です。

> C. 仮に立派な仕組み(メモリの自動的な安全管理、例外発生する時のstack的なメッセージ表示など)を独自で構築できても、所詮Java言語になるのではないでしょうか!?

C++ には Java にはない強力な機能(テンプレートなど)が備わっています。
それに、Java そっくりな立派な仕組みを作ったとしても、それを「使わない」という選択が可能なことが、C++ の最大の利点ですね。

> D. Javaなら、OSでさえ意識しなくてもいいような感じですね------工学や科学領域の処理内容(アルゴリズム)の多くはそもそもOSに依存すべきではないですから。

それだけ Java は対応可能な環境が限られているということです。Java でも、ちょっと変わった環境に対しては、OS を意識しなければなりません。例えば、JTRON 上のプログラムを書くのであれば、Java であっても OS を意識せざるを得ないでしょう。
C/C++ は、OS 無しの環境から、μITRON のような比較的簡単なカーネルや、Windows や Unix などのフルセットの OS まで対応していますし、OS そのものの記述にも使われるわけですから、ある程度 OS を意識するのはやむを得ないでしょう。
なお、C/C++ でも OS に依存しないプログラムを書くことは可能です。事実、私は仕事で OS に依存しないプログラムを日常的に書いています。

> E. 銀行業なら、Javaを選択するのは賢明に思います。

まあそうなのですが、人命に関わる自動車の制御プログラムは C で書かれているということをお忘れなく。
Java では時間的な制約のあるプログラムを書くのは困難なのです。例えば、ブレーキペダルを踏んだときに GC が走るとどうなるか、想像しただけでも嫌ですよね。

> F. OSやハードを制御するにのみ、(C)C++の強みでしょう。

他にも、先ほど書いたリアルタイム制御(必ずしも OS やハードの話ではありません)や、パフォーマンスが要求される場合は C/C++ ですね。
# Fortran の方がパフォーマンスがよい場合もあるわけですが...

tk-xleader

Re:コンストラクタからの例外送出(自分もショックな感想)

#39

投稿記事 by tk-xleader » 18年前

>A. C(C++)の場合、アルゴリズム以外、言語自身について(センテンスエラーレベルでなくて)
>いろいろ考えなければ危険が満ちています。

ある程度は安全になった面もあると思いますが、例えば…
コンストラクタ、デストラクタ
参照
STLのコンテナクラス。(特にvectorクラスやstringクラス、メモリリークなどの心配が少ない)
など。

速度はC/C++にかなうものってあるんでしょうか。たぶんアセンブリ言語ぐらいしか思いつきませんが。

GPGA

Re:コンストラクタからの例外送出(自分もショックな感想)

#40

投稿記事 by GPGA » 18年前

>たかぎさん

>この本はかなりレベルが高いので、もしかすると読み進めるのにかなり時間がかかるかもしれません。
>それでも、一通り読破すれば、C++に関する知識は格段に深まるはずです。
たかぎさんに「C++に関する知識は格段に深まるはず」とおっしゃっていただけると非常に心強いです。
今後も精進していきたいと思います。

> tkmakwins15さん
最近のC/C++のコンパイラが吐き出す最適化されたバイナリは侮れません。
20年くらい前からやっていたアセンブラプログラマが書くコードなら話は別ですが
私などのように、近年にプログラマになった人であれば、C/C++で書いて
コンパイラに最適化をかけさせたほうが、よほど速く動作します。

たかぎ

Re:コンストラクタからの例外送出(自分もショックな感想)

#41

投稿記事 by たかぎ » 18年前

> tkmakwins15さん
> STLのコンテナクラス。(特にvectorクラスやstringクラス、メモリリークなどの心配が少ない)

メモリリークの心配は少なくなりましたが、要素を追加したときに反復子が無効化するという罠がありますね。
それに、反復子の操作によって例外が送出されたり、一時オブジェクトが生成されたりという注意点も出てきます。

> GPGAさん
> 最近のC/C++のコンパイラが吐き出す最適化されたバイナリは侮れません。
> 20年くらい前からやっていたアセンブラプログラマが書くコードなら話は別ですが
> 私などのように、近年にプログラマになった人であれば、C/C++で書いて
> コンパイラに最適化をかけさせたほうが、よほど速く動作します。

大体の目安としてですが、8ビット CPU の場合であれば、経験の浅いプログラマであっても、おそらくアセンブリ言語で頑張った方が速いコードを書けると思います。
16ビット~32ビットになってくるとアーキテクチャにかなり依存します。パイプラインやスーパースカラのない CPU であれば、アセンブリ言語で速いコードを書くのもそれほど難しくないでしょう。RISC 用のアセンブラによっては、オペコードの並べ替えや命令の置換などの最適化を行ってくれるものもあるので、何ともいえませんね。

さば

Re:コンストラクタからの例外送出(お礼+雑談?)

#42

投稿記事 by さば » 18年前

::> たかぎ 様
とても立派なご返答に心からお礼を申し上げたいです。
一応C/C++でやってよかったという安心感を持ち始めました。
ただ、これからさらなる勉強と磨きが必要だと思います。

-----------------
>> D. Javaなら、OSでさえ意識しなくてもいいような感じですね------工学や科学領域の処理内容(アルゴリズム)の多くはそもそもOSに依存すべきではないですから。

>それだけ Java は対応可能な環境が限られているということです。Java でも、ちょっと変わった環境に対しては、OS を意識しなければなりません。例えば、JTRON 上のプログラムを書くのであれば、Java であっても OS を意識せざるを得ないでしょう。
-----------------
>> C. 仮に立派な仕組み(メモリの自動的な安全管理、例外発生する時のstack的なメッセージ表示など)を独自で構築できても、所詮Java言語になるのではないでしょうか!?

>.....それに、Java そっくりな立派な仕組みを作ったとしても、それを「使わない」という選択が可能なことが、C++ の最大の利点ですね。
-----------------

ご返答に哲学性富んでいます...

::> tkmakwins15 様

-----------------
>>A. C(C++)の場合、アルゴリズム以外、言語自身について(センテンスエラーレベルでなくて)
>>いろいろ考えなければ危険が満ちています。

>....参照 STLのコンテナクラス。(特にvectorクラスやstringクラス、メモリリークなどの心配が少ない)
など。
-----------------

私のようなC 時代から来た人間は「STLのコンテナクラス」のことを忘れがちですね。
これから最大限にSTLのコンテナクラスを利用したいです。

【以下は雑談中の雑談(?)】

*****************************************************************
人間の言語の場合、「言語比較学」あるらしい。
コンピュータ言語もいろいろ比較したら結構面白いのではと感じました。
*****************************************************************

皆さんによく指摘されているJavaのリアルタイム性の問題についてですが、
いつも不思議に思うのは、リアルタイム性のないくせに、なぜ、javaは携帯電話をはじめとして
組み込み系(ハードウェアに直結-----おそらくリアルタイム性が要求される)に
よく利用されているのでしょうかね。

また宜しくお願い致します。

たかぎ

Re:コンストラクタからの例外送出(お礼+雑談?)

#43

投稿記事 by たかぎ » 18年前

> 皆さんによく指摘されているJavaのリアルタイム性の問題についてですが、
> いつも不思議に思うのは、リアルタイム性のないくせに、なぜ、javaは携帯電話をはじめとして
> 組み込み系(ハードウェアに直結-----おそらくリアルタイム性が要求される)に
> よく利用されているのでしょうかね。

携帯電話は専門ではないので、それほど事情に詳しいわけではありませんが...
Java が使われているのは、本当に表面的な部分のアプリケーションだけですよね。下の階層になれば、C + リアルタイム OS が使われているはずです。

これは汎用機などでも言えることで、表面的なアプリケーションは COBOL などで書くとしても、下の階層は、やはり C やアセンブリ言語で書かれているはずです。

さば

Re:コンストラクタからの例外送出(お礼+雑談?)

#44

投稿記事 by さば » 18年前

たかぎ様
ご教授ほんとうにありがとうございました!

>Java が使われているのは、本当に表面的な部分のアプリケーションだけですよね。下の階層になれば、C + リアルタイム OS が使われているはずです。

なるほど。きっとそういうことでしょう。

また宜しくお願い致します

tk-xleader

Re:コンストラクタからの例外送出(お礼+雑談?)

#45

投稿記事 by tk-xleader » 18年前

>メモリリークの心配は少なくなりましたが、要素を追加したときに反復子が無効化するという罠がありますね。
>それに、反復子の操作によって例外が送出されたり、一時オブジェクトが生成されたりという注意点も出てきます。

そこには新たな危険も満ち溢れているということですね。自分もそこらへんは気をつけるようにします。

>最近のC/C++のコンパイラが吐き出す最適化されたバイナリは侮れません。
>20年くらい前からやっていたアセンブラプログラマが書くコードなら話は別ですが
>私などのように、近年にプログラマになった人であれば、C/C++で書いて
>コンパイラに最適化をかけさせたほうが、よほど速く動作します。

なるほど、「コンパイラの最適化」ということは全く考慮していませんでした。コードをそのままコンパイルした時の速度
を中心に考えていました。

バグ

Re:コンストラクタからの例外送出(お礼+雑談?)

#46

投稿記事 by バグ » 18年前

>>経験談ですけれども、
>>NULLポインタに対するdelete[/url]は決して何もしないわけではないようです。
>>すぐにはthrowしないかもしれませんが、その直後(どの時点については言えませんが)
>>必ずメモリエラー出ます(プログラムが強制中止されます)
>>これはVC6.0の時代でも VC2005の時代でも変わらないと思います。
>>皆さん経験されていません?

VC++2005では未確認ですが、VC++6.0では100%エラーが出ますね。
そんな訳で、私の場合はdeleteする前にポインタがNULLでない事を確認するようにしています。

バグ

Re:コンストラクタからの例外送出(お礼+雑談?)

#47

投稿記事 by バグ » 18年前

1つ前の書き込みですが、100%というのは言い過ぎでした。
今、試してみたら、何故かコンソールアプリではエラーになりませんでした…意味不明です。

たかぎ

Re:コンストラクタからの例外送出(お礼+雑談?)

#48

投稿記事 by たかぎ » 18年前

> VC++2005では未確認ですが、VC++6.0では100%エラーが出ますね。

念のため、VC++6.0で確認してみました。単純なWindowsアプリケーションとMFCの両方を試しましたが、いずれもエラーにはなりませんでした。これまでも、VC++6.0は何度も使っていますが、NULL を delete しておかしくなった記憶はありません。
未初期化のポインタを delete しているとかではないのでしょうか?

バグ

Re:コンストラクタからの例外送出(お礼+雑談?)

#49

投稿記事 by バグ » 18年前

いえ、間違いなく、コンストラクタ内でNULLを代入して初期化しています。

正直、ここのスレを見るまで、deleteが例外を返さないという事を知らなかったので、NULLチェックをしなければいけないものだと思ってましたし…(^_^;)

さば

Re:コンストラクタからの例外送出(やっぱり、なにか、、、)

#50

投稿記事 by さば » 18年前

>未初期化のポインタを delete しているとかではないのでしょうか?
これも犯した経験ありますね。
なぜ、コンパイルの段階で検出してくれないのでしょうか。

このような場合、"すぐ" + "必ず"メモリエラー出るのはまだ幸運なケースで、
怖いのはいつ、どんな形でトラブルが起きるかは分からないというのはC(C++)言語ですね。
定時爆弾の場合、置き場所や爆発時刻に関して少なくとも仕掛けた人は知っているはずですが、
C(C++)言語の場合ですね、その仕掛けた人(プログラマ)でさえ知る由はないということは恐怖きわまり。

銀行業務の場合、C(C++)のこんなトラブルで(いつ発生は分からないですが)一夜にして富豪が貧乏人になる可能性十分あります。(逆に成り立たない----貧乏人は銀行に貯金しないだから)

ブレーキ制御のようなロジック的には簡単で、短いシーケンス制御の場合、デバグやテストと実験は簡単なほうですが、
規模が大きい管理システム(多数人で開発した後、ドッキング)や、アルゴリズム複雑な工学的、科学的な場合、本当に長い間C(C++)と戦う経験者や記憶の優れた人でないと、どうなるでしょうかね。

またも恐怖感が起きてしまいました。

さば

Re:コンストラクタからの例外送出(やっぱり、なにか、、、(補足))

#51

投稿記事 by さば » 18年前

追伸:
大規模なアプリケーションの場合(ネット関連、DB関連)、フルケースのテストは不可能な場合もあります。
たとえフルケースのテストできても、C(C++)のメモリ関連の不都合(メモリリークなど)、
必ずしもテストのケースで起きるわけではない、、、、
本格稼動しはじめの時も起きない、、、、
幾つかの条件がそろえば、突然発生します。
そして、わけの分からない形で現れます、、、
なぜ?どうして?どこ?誰のせい?
判明には要時間.....最終的にはアプリケーションを放棄せざるを得ない?
(OS開発史上に実例があったような記憶もありますが)

どうもプログラマの優秀さに任せというのはやはり危険に感じます。
いくら優秀なプログラマでも時には微妙なミスを犯す場合あるでしょう。
それこそ見つかりにくくて、後になって、とんでもないトラブルを起こします。

やはり、
言語自身にはなんらかの仕組みで人間の過ちを防ぐのは正論のような感じですね。
なぜなら、ルールを従う視点からは機械のほうはどんな人間よりも「優秀」ですから。

たかぎ

Re:コンストラクタからの例外送出(やっぱり、なにか、、、)

#52

投稿記事 by たかぎ » 18年前

> またも恐怖感が起きてしまいました。

必要以上に迷信深くなっているような気がします。
自然を相手にしているわけではないので、言語仕様をちゃんと把握していれば何も怖いことはありません。
不可解な動きをすることがあるのは、最適化バグを踏んだときぐらいです(その場合でも、逆アセンブルリストを追えば大体尻尾はつかめます)。

まあ、C/C++ はともかく、癌細胞のようなコードを大量生成してくれる恐怖の自称プログラマに遭遇することは少なくありませんが...。

ところで、ブレーキ制御は思っているほど簡単ではありませんよ。
# ある意味、自然が相手の部分もあるので。

さば

Re:コンストラクタからの例外送出(やっぱり、なにか、、、)

#53

投稿記事 by さば » 18年前

::>たかぎ 様
>ブレーキ制御は思っているほど簡単ではありませんよ。

失礼致しました!
動的な過程(慣性システム)を制御することはまさに工学的、科学的なジャンルで、
複雑になる可能性十分あります。
(ただ、多くの簡単なシステムのシーケンス制御は比較的にテストしやすい)

tk-xleader

Re:コンストラクタからの例外送出(やっぱり、なにか、、、)

#54

投稿記事 by tk-xleader » 18年前

どうしても言語機能だけではミスはカバーできないんですね。どうしても人がプログラミングする以上は、細心の注意を払う必要があるようですね。

Re:コンストラクタからの例外送出(超雑談?)

#55

投稿記事 by » 18年前

>どうしても言語機能だけではミスはカバーできないんですね。どうしても人がプログラミングする以上は、細心の注意を払う必要があるようですね。

それはそのとおりでしょう。
特にロジック的、アルゴリズム的なミスと過ちはまったく人間の責任です。
ただ、それ以外の言語自身の特徴によるミスの性格はいろいろあるでしょう。
業務ロジックの遂行はCOBOLやFortrun、 MATLAB(科学技術系)は最高でしょう。
(言語自身の特徴によるミスの発生しやすさは比較的に低い)

CとC++はCPUのスピードが遅い、メモリ量が少ない時代においてその能率の優秀さは目立っていたのです。
僕も一番親しい感を持ち、馴染んでいる言語はCとC++です。
ただ、時代もCPUも変わっています。少なくとも実行のスピードの面において
現在ではCとJAVAの差はそれほどでもないと主張する人たちはいます。-----恐らくケース・バイ・ケース的でしょう。

JAVAのGCについてある程度制御できれば、
(例えば、クリティカル的な部分に対してGCのactive度合いを抑制できる#progmaのような印を与えばとか)
(現在のJAVAはこのような仕様になっていない?------確認していません)

勿論、少なくともしばらくはC++を使い続けたいです。
しかし、付き合いの年数からすれば、C++には大きな改革の必要性があるような感じですね。
これで、個人的にJAVAのことを注目したいのです。
JAVAは結構中道的で、バランスを取れた適切な言語かなと思います。

ちなみに、JAVAにはGeneric TypeがあってC++のtemplate classに当たるって、、、

それにしても、C++を放棄しろと言われたら、つらいですね。

*************************************************************************
JAVAにしろ、C++にしろ、関数の形に拘り過ぎは開発能率アップの障壁になっています。

表現の自然さと能率からすれば、やはりBATLABは一番汎用性高き、理想なモデルだと思います。
勿論、どの言語も欠点はありますが。
*************************************************************************

tk-xleader

Re:コンストラクタからの例外送出(超雑談?)

#56

投稿記事 by tk-xleader » 18年前

>勿論、どの言語も欠点はありますが

欠点というのはこのような感じでしょうか?
C → 高度なプログラミングにはポインタがつき物、型チェックが甘い
C++ → 仕様が肥大化したこと、人のミスに対する考慮が薄い
JAVA → 速度の問題?
C# → 特定の環境に依存する。(.NET)
(これぐらいしかわかりません。何しろ中学生ですので。)

言語の使い分けはこのような欠点と利点において最優先すべき利点がある言語を選択するということになるのでしょうか。

さば

これこそC/C++の欠点の現れでは

#57

投稿記事 by さば » 18年前

現に君のような中学生でさえ、おいらのような古参よりも上になる可能性が高いということは
まさにC/C++の欠点の現れだと思う。
要は人の記憶に頼りすぎ。

肥大化した仕様や微妙なところは散々だと、やっぱり機械処理や記憶のいい年に向いているよね。

さば

コンストラクタからの例外送出(超雑談?)に訂正

#58

投稿記事 by さば » 18年前

>表現の自然さと能率からすれば、やはりBATLABは一番汎用性高き、理想なモデルだと思います。
勿論、どの言語も欠点はありますが。

[誤] "BATLAB"
[正] "MATLAB"

tk-xleader

Re:コンストラクタからの例外送出(超雑談?)に訂正

#59

投稿記事 by tk-xleader » 18年前

>現に君のような中学生でさえ、おいらのような古参よりも上になる可能性が高いということは
>まさにC/C++の欠点の現れだと思う。
>要は人の記憶に頼りすぎ。

それが安全性の犠牲というものでしょうか。確かにC/C++はプログラマの能力に依存しているところが多いと思います。
しかし、僕はやはりまだまだレベルは低いですよ。実際のところC/C++しかよく分かりませんし。

管理人

Re:コンストラクタからの例外送出(超雑談?)に訂正

#60

投稿記事 by 管理人 » 18年前

さばさん、こちらにフリーメールでいいのでメールを送っていただけませんでしょうか。
お話したいことがありますので。
→ dixqhp@gmail.com

閉鎖

“C言語何でも質問掲示板” へ戻る