通用类库 - 错误、说明、问题、使用功能和建议 - 页 26

 
Andrey Pogoreltsev:

你在AddValue中通过new创建了对象的副本,但你并没有在析构器中释放它们,你只是清除了指针的列表。

帮助说,当你调用一个析构器时,你所用的类的析构器也会被调用。

https://www.mql5.com/ru/docs/standardlibrary/datastructures/carrayobj#carrayobjfeatures

我不记得有什么情况是终端在卸载脚本后没有在日志中写入关于未销毁对象的警告--我的例子中没有显示这样的警告


安德烈-波戈雷尔采夫

其次,你应该用复制构造器而不是赋值运算符来正确地完成它。但这都是IMHO)

我从开发人员那里发现,MQL中的简单结构或类的复制总是没有问题的,我检查了几次,似乎是真的,直到我使用了语言的特性


这就是讨论的内容--MQL不是C++,我已经不再寻找它们之间的类比了,开发者写道,这就是它的实现方式--我检查过了,它是可行的--所以你可以使用它,如果标准的C++语法是关键,你可以很容易地在.dll中写下所有的逻辑

Документация по MQL5: Стандартная библиотека / Коллекции данных / CArrayObj
Документация по MQL5: Стандартная библиотека / Коллекции данных / CArrayObj
  • www.mql5.com
Класс CArrayObj обеспечивает возможность работы с динамическим массивом указателей на экземпляры класса CObject и его наследников. Это дает возможность работы как с многомерными динамическими массивами примитивных типов данных, так и с более сложно организованными структурами данных. В классе реализованы возможности добавления/вставки/удаления...
 
Andrey Pogoreltsev:

你在AddValue中通过new创建对象的副本,但你在析构器中并没有释放它们,你只是清除了指针列表。

哦,亲爱的!你怎么能删除一个通过析构器中的new创建的类的实例呢。试着去做。它不会起作用。

你只能在其他类的析构器中这样做。

 
Nikolai Semko:

哦,该死!你怎么能删除一个通过析构器中的new创建的类的实例呢。你可以试试。它不会起作用。

你只能在另一个类的析构器中做到这一点。

我说的是另一个类的析构器。我说的是在AddValue 方法中通过new创建的项目。

 
Igor Makanu:

帮助说,当一个析构器被调用时,所使用的类的析构器也将被调用。

https://www.mql5.com/ru/docs/standardlibrary/datastructures/carrayobj#carrayobjfeatures

我不记得有什么情况,在脚本卸载后,终端没有在日志中写下关于未销毁对象的警告 - 我的例子中没有显示这样的警告。


我从开发人员那里听说,MQL中的简单结构或类的复制总是没有任何问题的,我检查了几次,似乎是真的,到目前为止,我使用该语言的可能性。


这就是讨论的内容--MQL不是C++,我已经不再寻找它们之间的类比了,开发者写道,这就是它的实现方式--我检查过了,它是有效的--所以你可以使用它,如果标准的C++语法是关键,我应该不用担心把所有的逻辑放到.dll中。

是的,我在帮助中看到了它...非常隐性的东西,看起来更像是一个拐杖,而不是unique_ptr...

 
Andrey Pogoreltsev:

是的,我在帮助中看到了它...非常隐性的东西,更像是一个拐杖,而不是unique_ptr...

而且它非常方便,我甚至不能说它是一根拐杖。

创建一个任何类别的对象,把它放在一个存储列表中,你不必再担心删除它--终端子系统会自己清理它。
但你也可以为所有新创建的对象设置手动操作和 "运行",试图跟踪它是在何时、何地、出于何种目的创建的,以及现在是否需要它。如果不需要,请删除它。但当你犯了一个错误时,事实证明它是需要的--当访问一个无效的指针时,它崩溃了......

因此,拐杖只是 "追逐对象",寻找它们的无用之处,并担心如果某些对象还没有被赶上,会出现内存泄漏。

 
Andrey Pogoreltsev:

其次,正确的做法是使用复制构造器而不是赋值运算符。但这都是IMHO)

你能给我一个例子,说明如何为这个模板正确地复制它吗?

template<typename T>class CDataBase
  {
private:
   CList            *mlist;
   T                *Tptr;
public:
   void CDataBase()           { mlist=new CList;                                       }
   void ~CDataBase(void)      { delete mlist;                                          }
   int ArraySize(void)        { return(mlist.Total());                                 }
   T *operator[](int index)   { return(mlist.GetNodeAtIndex(index));                   }
   void  AddValue (T &value)  { Tptr = new T; Tptr  = value; mlist.Add(Tptr);          }
   string TypeName()          { return(typename(T));                                   }
  };

我用帮助写了AddValue方法https://www.mql5.com/ru/docs/basis/types/classes

我绞尽脑汁,但在MQL中,除了我在例子中写的那个,我没有看到任何其他的解决方案

让我看看你对正确的数据存储的实施

Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
Документация по MQL5: Основы языка / Типы данных / Структуры, классы и интерфейсы
  • www.mql5.com
Структура является набором элементов произвольного типа (кроме типа void). Таким образом, структура объединяет логически связанные данные разных типов. Объявление структуры Имя структуры нельзя использовать в качестве идентификатора (имени переменной или функции). Следует иметь ввиду, что в MQL5 элементы структуры следуют непосредственно друг...
 
Artyom Trishkin:

而且它非常方便,你甚至不能说它是一根拐杖。

创建任何类别的对象,将其放入存储列表,你不必再担心删除它--终端子系统会自己清理它。
但你也可以设置手动操作,对所有新创建的对象进行 "运行",试图找出它是何时、何地、出于何种目的创建的,以及现在是否需要它。如果不需要,请删除它。但当你犯了一个错误时,事实证明它是需要的--当访问一个无效的指针时,它崩溃了......

因此,拐杖只是 "追逐对象",寻找它们的无用之处,并担心如果某些对象还没有被赶上,会出现内存泄漏。

我在这里的意思是,当你把一个指针添加到集合中时,它也会留在你身边。这是第一件事。

第二,我们不是在谈论数组-收集和连续阅读,你有一个碎片化的系统。

第三,没有人能够保证你传递的指针准确地指向集合对象。
 
Andrey Pogoreltsev:
这里的重点是,一旦你把一个指针添加到集合中,它也会一直跟着你。这是第一件事。

第二,我们不是在谈论数组-收集和连续阅读,你有一个碎片化的系统。

第三,没有人保证你传递了一个指向集合对象的指针。
  1. 我的意思是,终端子系统自动删除你所有创建的对象并把它们的指针放在列表中,你称之为拐杖,而你不认为手动操作你的对象并为其创建拐杖是拐杖。
  2. 这不是你在第一项中所说的一部分,也是我回应的主要原因。
  3. 这也是,而且是出于同样的原因。
[删除]  
Igor Makanu:

帮助说,当解构器被调用时,所使用的类的解构器也将被调用。

https://www.mql5.com/ru/docs/standardlibrary/datastructures/carrayobj#carrayobjfeatures

我不记得有什么情况,在脚本卸载后,终端没有在日志中写下关于未销毁对象的警告 - 我的例子中没有显示这样的警告。


我从开发人员那里听说,MQL中的简单结构或类的复制总是没有任何问题的,我检查了几次,似乎是真的,到目前为止,我使用该语言的可能性。


这就是讨论的内容--MQL不是C++,我已经放弃寻找它们之间的类比,开发人员写道,这就是它的实现方式--我检查过了,它是可行的--所以你可以使用它,如果标准的C++语法至关重要,你可以很容易地在.dll中编写所有的逻辑。

能否用这个制作一个三角形阵列?

[删除]  

由于语言的限制,不太可能有什么像样的东西可以用。我有这个拐杖(在标准数组上的一个轻量级包装)。

#define  GENERATE_VECTOR_GROWTH_FACTOR 2
#define  GENERATE_VECTOR(NAME, REF)                                         \  
   template <typename T>                                                   \
   class NAME                                                              \
   {                                                                       \
      int sz;                                                              \
      bool fail_state;                                                     \
   public:                                                                 \
      T a[];                                                               \
      NAME(): sz(0), fail_state(false) {}                                  \
      bool operator!()const      {return this.fail_state;}                 \
      uint size()const           {return this.sz;}                         \
      void clear()               {this.sz = 0; this.fail_state = false;}   \
      void push_back(T REF value) {                                        \
         if (this.sz == ArraySize(this.a)  &&                              \
             ArrayResize(this.a, this.sz*                                  \
                           GENERATE_VECTOR_GROWTH_FACTOR+1) == -1) {       \
            this.fail_state = true;                                        \
            return;                                                        \
         }                                                                 \
         this.a[this.sz++] = value;                                        \
      }                                                                    \
      void reserve(int new_cap) {                                          \
         if (new_cap > ArraySize(this.a))                                  \
            ArrayResize(this.a, new_cap);                                  \
      }                                                                    \
      void erase(int pos) {                                                \
         if ( ! ArrayRemove(this.a, pos, 1) )                              \
            this.fail_state = true;                                        \
      }                                                                    \
   };
#define  GENERATE_VECTOR_EMPTY
GENERATE_VECTOR(vector_fund, GENERATE_VECTOR_EMPTY);  // для фундаментальных типов
GENERATE_VECTOR(vector_ref, const &);                 // для пользовательских
#undef  GENERATE_VECTOR_EMPTY
#undef  GENERATE_VECTOR_GROWTH_FACTOR

struct S {int a;};
class Q {};
bool f() {
   vector_ref<S> v1;
   vector_fund<int> v2;
   vector_ref<Q> v3;
   
   Q q;
   v3.push_back(q);
   v2.push_back(3);
   v2.a[0] = 5;
   
   return !(!v1 || !v2 || !v3);
}

为了存储指针,写一个unic_ptr包装器(虽然你不能得到一个完整的包装器,但至少是auto_ptr)。在我看来,即使是这种原始的东西也比std的模板对应的东西要方便得多。