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

 
Stanislav Korotky:

関数から無名オブジェクトのインスタンスを返す方法はありますか?

マクロに置き換える。
 
fxsaber:
マクロに置き換える。

うまくいかない。これはクラスメソッド であり、paramは実際にはオブジェクトから取得されます。ここでは例として簡略化しています。

 
Stanislav Korotky:

うまくいかない。これはクラスメソッド であり、paramは実際にはオブジェクトから取得されます。ここでは例として簡略化しています。

もちろん、本来のタスクに慣れた方がいいのですが...。

ポインターを返すのは間違いでしょうか?

 

Stanislav Korotky:

内部コピーが余分に作成 されることと、return文でクラス内にコピーコンストラクタが必要 なことを除けば、動作 します。関数の終了時にコピーに釘付けになるが、コピーそのものをなくしたい。


Class function()
{
  int param = 0;
  Class obj(param);
  return obj;
}

もちろんそうです。ローカル変数は関数が終了するときに破棄されます。
newを使ってポインターを返す、何が問題なのか?

リソースの制御が必要な場合は、スマートポインタのようなラッパーを使用します。
シングルトンやビルダーのようなCreational Patternsの何かを使うことができるかもしれない...。

 
fxsaber:

もちろん、本来の仕事に慣れるのが一番ですが...。

ポインターを返すのは間違いでしょうか?

それは、もともとポインターの上にあったものです。しかし、その場合、クライアントコードがそれらを削除する責任を負い、それは多くのゴミであり、言うまでもなく、瞬きをしている間に中断されたリンクが残ってしまうのです。

 
Sergey Dzyublik:

もちろんそうです。関数を終了すると、ローカル変数は破棄されます。

newを使ってポインターを返す、何が問題なのか?

リソースの制御が必要な場合は、スマートポインタのようなラッパーを使用します。
シングルトンやビルダーのようなCreational Patternsの何かが、あなたのために働くかもしれません。

ポインターがある→不便(上記で回答済み)。スマートさ」のほうに目を向けてみました。しかし、私の印象では、MQLではスマートポインタは参照性のレベルをもう一つ上げるだけで、順番に監視していく必要があります。結局のところ、スマートポインターとは何なのか?- これは、初期参照が置かれるラッパーオブジェクトです。そして、誰が、いつ、包装紙をきれいにするのか。;-)もし、解決策があるのなら、ぜひ教えてください。とりあえずテストケースを用意しました。

 
Stanislav Korotky:

結局のところ、スマートポインターとは何なのか?- これは、元の参照が配置されるラッパーオブジェクトである。そして、誰が、いつ、包装紙をきれいにするのか。;-)もし、解決策があるのなら、ぜひ教えてください。とりあえずテストケースを用意しました。


shared_ptrを使用します。
このラッパーのクリーニングは必要なく、コピーするだけで、shared_ptrは目的のリソースのインスタンスがいくつ残っているか、いつこのリソースやあのリソースを解放するかを示しています。


少なくとも私には、既成の解決策はありません。C++のものを適応させる。

 
Sergey Dzyublik:

少なくとも私には、既成の解決策はありません。C++のものを適応させる。

それは理解できるのですが、すでにMQLでは「トレース」を作ることができないという印象があるのです。

 
Stanislav Korotky:

関数から無名オブジェクトのインスタンスを返す方法はありますか?

ここで既に誰かが指摘しているように、最も正しい方法は、関数からスマートポインタを返すことです。これらはすべてMQLで実装されています。しかし、ポインタ渡しはパス演算子ではなく、メソッドで実装する必要があるため、C++のように便利に使うことはできない。ちなみに、今回のタスクではshared_ptrは必要なく、unique_ptrで十分だと思います。

また、関数内で生成されたポインタを直ちに何らかのグローバル配列に配置し、プログラム終了時にゴミ箱に入れることも可能です。同時に、ユーザーは特別な関数を呼び出すことで、いつでもオブジェクトのメモリを解放することができます(削除はできません)。WinApiのCloseHandleのようなものです。

内部コピーが余分に作られることと、リターン演算子で クラス内にコピーコンストラクタが必要なことを除けば、うまくいきます。関数の終了時にコピーに釘付けになるものの、コピー自体をなくしたいと思っています。

おそらく、コンパイラは賢いので、不要なコピーを除いて、自分ですべてを最適化してインライン化するのでしょう。でも、確認はしないといけない。誰かがテストや計測をしてくれるといいのですが。なぜなら、私自身もそのようなジレンマに陥ることが多いからです。

 
Alexey Navoykov:

すでにどなたかが指摘されているように、正しい方法は関数からスマートポインタを返すことです。これらはすべてMQLで実装されています。しかし、ポインタの切り替えはswitch演算子ではなく、メソッドで実装しなければならないので、C++のように使い勝手が良いとは言えません。ちなみに、今回のタスクではshared_ptrは必要なく、unique_ptrで十分だと思います。

また、関数内で生成されたポインタを直ちに何らかのグローバル配列に配置し、プログラム終了時にゴミ箱に入れることも可能です。同時に、ユーザーは特別な関数を呼び出すことで、いつでもオブジェクトのメモリを解放することができます(削除はできません)。WinApiのCloseHandleのようなものです。

おそらく、コンパイラは賢いので、すべてを最適化して勝手にインライン化し、不要なコピーを排除してくれるのでしょう。でも、確認はしないといけない。誰かがテストや測定を実施してくれるといいのですが。そうでなければ、私もよくそのようなジレンマに直面することになります。

以下に私の実装を公開します。とにかく、これらのスマート・ポインタは一時的に作成されるもので、結果的に私は持っていた以上のオブジェクトを作成して釘付けにしているだけです;-)。

もちろん、グローバル配列の変形を念頭に置いていますが、とても不格好です特に、私はタイマーで掃除したかったので(プログラムが何日も実行される可能性があるため)、MQLのタイマーはクラス/オブジェクトにアタッチすることができず、グローバルハンドラから来るだけです。

コンパイラはここでは役に立ちません - テスト済み - 戻り値のローカルオブジェクトが複製され、その後釘付けにされます。この場合、最適な手はありません。

template<typename T>
class auto_ptr
{
  private:

    class Reference
    {
      public:
        int count;
        Reference(): count(0) {}
    };

    T *data;
    Reference *reference;

    void remove()
    {
      if(reference != NULL)
      {
        reference.count--;
        if(reference.count == 0)
        {
          delete data;
          delete reference;
        }
      }
    }

    
  public:
    auto_ptr(): data(NULL), reference(NULL)
    {
    }
    auto_ptr(T *ptr): data(ptr), reference(ptr == NULL ? NULL : new Reference())
    {
      if(reference != NULL) reference.count++;
    }
    auto_ptr(auto_ptr<T> &ref): data(ref.data), reference(ref.reference)
    {
      reference.count++;
    }
    
    ~auto_ptr()
    {
      remove();
    }
    
    void operator=(auto_ptr<T> &next)
    {
      if(&this != &next)
      {
        remove();
        
        data = next.data;
        reference = next.reference;
        reference.count++;
      }
    }
};