エラー、バグ、質問 - ページ 2198

 
fxsaber:

差支えありません


入力時は、入力した数字に依存するようです。中には文字が打てないものもあります。そして、そのうちのいくつかは、そうです。

奇妙な行動...12桁未満の整数を入力すると、14桁以上の合計をスキップする場合があります。

開発者の意見を待ちたいと思います。

 
簡単なことですが、よろしくお願いします
class A
{
public:  
  int i;
  
  A* operator *( const A &Value ) const
  {
    A* Res = new A;
    
    Res.i = this.i * Value.i;
    
    return(Res);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A* d = a * b * c;
  
  Print(d.i); // 30
  
  delete d;
}

コードを見ると、明らかにメモリリークがあるはずです。そして、その通りのことが起こっているのです。しかし、どのように書けば、物体の「掛け算」ができるようになるのでしょうか。構造体の場合と同様、"*="演算子ですべてが解決します。しかし、クラスでは、この単純な機能をどのように実装すればよいのでしょうか。


SZZ そしてこのコード。

class A
{
private:
  A Tmp;
  
public:
  int i;
  
  A* operator *( const A &Value )
  {
    this.Tmp.i = this.i * Value.i;
    
    return(&Tmp);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A* d = a * b * c;
  
  Print(d.i); // 30
}

F7でMEをクラッシュさせ、F5でTerminalを終了させる。どうして私はこんなにラッキーなんだろう!

 
fxsaber:

ZS そしてこのコード

F7でMEがクラッシュし、F5でTerminalが終了します。どうして私はこんなにラッキーなんだ!

class A
{
private:
  A Tmp;
  
public:
  int i;
  
  A* operator *( const A &Value )
  {
    this.Tmp.i = this.i * Value.i;
    
    return(&Tmp);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A* d = a * b * c;
  
  Print(d.i); // 30
}

おそらく無限再帰とスタックオーバーフローでしょう。

 
Sergey Dzyublik:

無限再帰とスタックオーバーフローの可能性があります。

確かに問題は割り当てられたほうにあるのですが、原因はもっと深いところにあるようです。

また、実行時に再帰が発生してはならないことは明らかです。

 
fxsaber:
簡単なことですが、よろしくお願いします
class A
{
public:
  A() {}
  A(const A& other) 
  {
   this.i = other.i;
  }
  
  int i;
  
  A operator *( const A &Value ) const
  {
    A Res;
    
    Res.i = this.i * Value.i;
    
    return(Res);
  }
};

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A d = a * b * c;
  
  Print(d.i); // 30
}
もちろんオーバーヘッドですが、利便性を重視するならば...。
 
Комбинатор:
もちろんオーバーヘッドはあるだろうが、利便性を重視するならば...。

ありがとうございました。オブジェクトを定義する際に、return objectと"="は追加のコンストラクタを経由することが判明しました。

本当は、どの場合をコンストラクタと呼び(どの場合を)、どの場合をオペレータと呼ぶのか、どこかに明確な表が欲しいところです。今はすべてが直感的で、当然ながら失敗します。

 
fxsaber:

本当は、コンストラクタがどこで(どのコンストラクタが)呼ばれ、オペレータがどこで呼ばれるのか、どこかに表が欲しいところです。今はすべて直感のレベルで、当然ながら失敗します。

値で何かを返す場合、それが定義であればコピーコンストラクタ(同じ型の場合)、そうでなければオペレータを介して代入されます。

void OnStart()
{
  A a, b, c;
  
  a.i = 2;
  b.i = 3;
  c.i = 5;
  
  A d = a * b * c;
  // код аналогичен A d(a * b * c);
  // будет вызван копи-конструктор.

  A e;
  e = a * b * c;
  // будет вызван оператор =
  // но копи-конструктор все равно нужен для множественного умножения
  
  Print(d.i); // 30
}
 
Комбинатор:

値で何かを返す場合、それが定義であればコピーコンストラクタ(同じ型の場合)、そうでなければ演算子で代入されます。

明瞭な表現、ありがとうございました


SZZはあなたのコードを呼び出します。

class A
{
public:
  A() { Print(__FUNCSIG__); }
  A(const A& other) 
  {
   Print(__FUNCSIG__);
   this.i = other.i;
  }
  
  ~A()
  {
   Print(__FUNCSIG__);
  }
  
  int i;
  
  A operator *( const A &Value ) const
  {
    Print(__FUNCSIG__);

    A Tmp;
    
    Tmp.i = this.i * Value.i;
        
    return(Tmp);
  }
};

void OnStart()
{
  if (true)
  {
    A a, b, c;
    
    a.i = 2;
    b.i = 3;
    c.i = 5;
    
    A d = a * b * c;

    Print(d.i); // 30
  }
  
  Print("Kill!");  
}


結果

void A::A() // a
void A::A() // b
void A::A() // c
A A::operator*(const A&) const
void A::A() // Tmp
void A::A(const A&) // return
void A::~A() // Tmp
A A::operator*(const A&) const
void A::A() // Tmp
void A::A(const A&) // return
void A::~A() // Tmp
void A::A(const A&) // d
30
void A::~A() // a
void A::~A() // b
void A::~A() // c
void A::~A() // d
void A::~A() // return
void A::~A() // return
Kill!

ハイライトされた行は、疑問を投げかけるものです。なぜテンポラリーオブジェクトが使用されるとすぐにクラッシュしなかったのでしょうか?つまり、30を出力する前に。このようなオブジェクトは、数千万ティックを処理することになっているため、私のマシンをクラッシュさせてしまうでしょう。各オブジェクトはギガバイトのRAMを食い尽くすので、すぐに殺すのではなく、そのような一時的なオブジェクトは持ちたくないのです。

 
fxsaber:

ハイライトされた行は、疑問を投げかけるものです。なぜテンポラリーオブジェクトが使用されるとすぐにクラッシュしなかったのでしょうか?つまり、30歳の出力前です。

通常、一時的なオブジェクトはすぐに削除されず、コンテキストの終了時に削除されます。

高速に削除したい場合は、コンテキストを制御します。

void OnStart()
{
  if (true)
  {
    A a, b, c;
    
    a.i = 2;
    b.i = 3;
    c.i = 5;
    
    A d;
    {
      d = a * b * c;
    }

    Print(d.i); // 30
  }
  
  Print("Kill!");  
}

True の場合、演算子 = を使用する必要があります。

 
A100:

私の新しいグラフでは、例題は再起動したとき(すべてのボタン)しか動作せず、それ自体理解不能です。しかし、今、私はこれを理解しています。

トレードの開始とともに、指定した効果がなくなる(再起動時のみ)

ドキュメントの編集を行いました。このコードの問題点は、マウスイベントの命令をチャートに送っても、その命令をチャートのキューに入れるだけだということでした。また、このキューが処理されない場合(週末など)、チャートは指定されたイベントを受信することができません。ChartSetIntegerの 説明文に注釈と修正例を追加。

備考

この関数は非同期式です。つまり、指定したチャートに対して正常にキューイングされたコマンドの実行を待たずに、直ちに制御を戻すことを意味します。このプロパティは、コマンドがグラフキューで処理された後にのみ変更されます。チャートキューのコマンドを即座に実行するには、ChartRedraw 関数を呼び出す必要があります。

複数のチャート・プロパティを直ちに変更する必要がある場合、適切な関数 (ChartSetString,ChartSetDouble,ChartSetString) を一つのコードブロック内で実行し、その後ChartRedraw を 一度呼び出さなければなりません。

実行結果を確認するには、指定したチャートプロパティを問い合わせる関数(ChartGetInteger,ChartGetDouble,ChartSetString)を使用することができます。なお、これらの関数は同期式で、実行結果を待ちます。

//+------------------------------------------------------------------+
//| エキスパート初期化機能|
//+------------------------------------------------------------------+
voidOnInit()
{
//--- チャートウインドウでのマウスの動きに関するメッセージを有効に する
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
//--- チャートのプロパティを強制的に更新することで、イベント処理の準備を 確実にします
ChartRedraw(
);
}