MQL5 コンパイラはクラスとそのポインタを区別しない - ページ 5

 
記号は、あるオブジェクトのメモリ領域を別のオブジェクトのメモリ領域にコピーします。すべてのオブジェクトは元の場所に残ります。
 
Vladimir Simakov:
きっかけがないんです。純粋なメモリーリークです。

召喚できるようにする。

 

ところで、開発者の皆さん、これは直した方がいいですよ。結局のところ、newはポインタを返すので、もう一方の端で=もポインタであることのチェックを追加し、暗黙の変換を削除します (A) new A(); 私はそれを理解として - これは何が起こるかです。

 
Vladimir Simakov:

ところで、開発者の皆さん、これは直した方がいいですね。結局のところ、newは本当にポインタを返すので、もう一方の端=もポインタであることのチェックを追加し、暗黙の変換(A)new A();を削除する - 私はそれを理解したように、これは何が起こるかです。

このオペレーターの募集があります

トレーディング、自動売買システム、ストラテジーテストに関するフォーラム

MQL5 Compilerは、クラスとポインタを区別しない

fxsaber, 2019.01.10 06:36

いつから定義されたのか(開発者への質問)

void A::operator =( const A& );
void A::operator =( const A* );

そして、その仕組みは?以下のコンパイルされたコードは、妄想に見えます。

    A* b = NULL;    
    m_A[1] = b;    


大雑把に言うと、以下のような感じです。

class A
{
public:
    int iValue;
    
    void operator =( const A* Ptr )
    {
      Print(__FUNCSIG__);
      
      this.iValue = Ptr.iValue;
    }
};
//......................
A m_A[2];

void OnStart()
{
A a;

    m_A[0] =a; 
    m_A[1] = new A();
}
 
fxsaber:

このオペレータへの呼び出しがある


大雑把に言うと、以下のような感じです。

ああ、わかったよ。悪くないレーキだと思います。ちなみに、この演算子オーバーロード=はC++には存在しない、とVSは断言している。
 

騒ぐ前に、MQLではポインターは暗黙のうちにオブジェクトにキャストされる(デリファレンスされる)ことを知っておくと便利だし、誰もがそれに慣れる。読みにくいa()->b()->c()->d() の 代わりに、通常の OOP 形式で書くことができます。a().b().c().d() と、関数に渡すときに不要な変換をする必要がありません。 それなのに、誰かの不満のためにすべてを変更するのですか?

 
Alexey Navoykov:

MQLでは、ポインターは暗黙のうちにオブジェクトにキャストされる(デリファレンスされる)ので、便利だし、みんなそれに慣れているのです。読みにくいa()->b()->c()->d() の 代わりに、通常の OOP 形式で書くことができます。a().b().c().d() と、関数に渡すときに不要な変換をする必要がありません。 なのに、誰かの不満のためにすべてを変えるのですか?

キャスティングがどうのこうのということではありません。ハマらなかったんですね。

 

MQL - C++の宣言されたプロトタイプに導かれるなら。

C++では、new 演算 子は、m_A がオブジェクトの配列の場合、それぞれポインタを返します。

m_A[1] = new A();

は型エラーになります。

これは、コンパイラがスキップしてしまう行です。

m_A[1] = *( new A() );

しかし、それではメモリリークが発生してしまいます。


MQLにも同じような動作があればいいのですが。

 
Alexey Navoykov:

この問題について騒ぎ出す前に、MQLではポインターは暗黙のうちにオブジェクトにキャストされ(デリファレンスされ)、便利で誰もがそれに慣れたことを知っておく必要があります。読みにくいa()->b()->c()->d() の 代わりに、通常の OOP 形式で書くことができます。a().b().c().d() と、関数に渡すときに不要な変換をする必要がありません。 なのに、誰かの不満のためにすべてを変更するのですか?

そして、簡単な例を挙げて詳しく説明すると。

A a;

// 'a' ожидает объект
 
a = new A(); // а ему дают указатель, ведь можно же

// что в MQL равнозначно?
a = *(A*) new A();

その結果、私たちは

1.a' が生成されたオブジェクトの コピーを取得すると、生成された新しいオブジェクトへのポインタが失われる

2.newでオブジェクトの生成/メモリ確保に失敗した場合、aはどうなるか?

第二の場合(逆に)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)
a = &b;

1.関数終了後、ローカルオブジェクトとして 'b' オブジェクトを破棄する必要があります。

では、「a」は何を指すのでしょうか。

2. それとも、コピー演算子はまだ働いて、'b' は 'a' ポインタによってコピーされるのでしょうか? また、'a' が以前に定義されていない場合はどうでしょうか?

 
SemenTalonov:

第二の場合(逆に)

A* a; // глобальный указатель - 'a' ожидает указатель на объект

// далее всё происходит внутри некой функции
A b; // создаем второй в стеке (ну типа в стеке, не суть)

a =b;
// т.е. тут объект "неявно кастится" к указателю?)


ここではその逆で、ポインタaを 暗黙のうちにオブジェクトにキャスト(デリファレンス)して、それにoperator=を適用しています。

論理的にはMQLのルールと矛盾しませんが(operator=の呼び出しは他のオブジェクト・メソッドの呼び出しと同等なので)、このようなコードの曖昧な理解や見つけにくいエラーにつながります。また、これはoperator=だけでなく、少なくとも==と!=にも関係します。 C++では、+-<>[]という演算子を適用することができるので、おそらく他の演算子についてもこのようなキャスティングを禁止すべきなのでしょう。

つまり、C++でポインタに対して許可されている演算子をポインタに適用する場合、このポインタをオブジェクトに暗黙的にキャストすることを許可しないということです。 これに対応して、上記の例ではコンパイルエラーが 発生します。