mql5语言的特点、微妙之处以及技巧 - 页 110

 

关于交易、自动交易系统和交易策略测试的论坛

虫子,虫子,问题

fxsaber, 2018.12.01 11:15

超级制动器设计
string Str[];
const int handle = FileOpen(FileName, FILE_READ | FILE_ANSI | FILE_TXT);  

FileReadArray(handle, Str);

一个40Mb的100万行的文件需要18秒的时间来读取。


同样的输出结果,但以不同的方式进行

  uchar Bytes[];
  const int handle = FileOpen(FileName, FILE_READ | FILE_BIN);
  
  FileReadArray(handle, Bytes);

  string Str[];
  StringSplit(CharArrayToString(Bytes), '\n', Str);

已经在0.5秒内完成。


 
编译的一个人为技巧
#define  MACROS(A, B) A / B + !(A / B) // (A >= B) ? A / B : 1

template <typename T1, typename T2>
union UNION
{
  T1 a;
//  T2 b[sizeof(T1) / sizeof(T2)];      // '[' - invalid index value
  T2 b[MACROS(sizeof(T1), sizeof(T2))]; // OK
};

template <typename T1, typename T2>
void f()
{
  if (sizeof(T1) >= sizeof(T2))
    UNION<T1, T2> Union;
  else
    UNION<T2, T1> Union;  
}

void OnStart()
{
  f<int, char>();
}
 

与auto_ptr(被认为是过时的)的简单对应。注:不完全类似,有
...


https://habr.com/post/140222/

Smart pointers для начинающих
Smart pointers для начинающих
  • habr.com
Эта небольшая статья в первую очередь предназначена для начинающих C++ программистов, которые либо слышали об умных указателях, но боялись их применять, либо они устали следить за new-delete. UPD: Статья писалась, когда C++11 еще не был так популярен. Итак, программисты С++ знают, что память нужно освобождать. Желательно всегда. И они знают...
 

pavlick_

在开头的一行应该加在operator=上。

if (p==other.p) return &this;
 

尽管可能值得把自己限制在这样的范围内(你根本不能复制)。

template <typename T_>
class unique_ptr{
   T_ *p;
public:
   unique_ptr(void *ptr=NULL): p(ptr)           {}
   ~unique_ptr()                                {reset();}
   unique_ptr *operator=(T_ *p_)                {reset(); p = p_; return &this;}
   // releases ownership of the managed object
   T_ *release()                                   {T_ *r = p; p = NULL; return r;}
   // destroys the managed object 
   void reset()                                    {if(p) delete p; p=NULL;}
   // returns a pointer to the managed object 
   T_ *get()                                       {return p;}
   unique_ptr(const unique_ptr<T_> &other);
   void operator=(const unique_ptr<T_> &other);
   void swap(unique_ptr<T_> &other){
      T_ *buf = p;
      p = other.p;
      other.p = buf;
   }
};
我为什么要为auto_ptr做复制?由于μl的曲率--要把堆栈对象复制到CArrayObj,你必须通过多次调用构造函数来创建一堆对象。但我认为这并不值得。在这方面,我将记下第一个帖子。
 
pavlick_:

我为什么要为auto_ptr做复制?由于μl的曲率--要复制一个堆栈对象到CArrayObj,你必须通过多次调用构造函数来创建一堆对象。

而为什么是 "μl的曲率"?

 
Alexey Navoykov:

还有,为什么会出现 "µl的歪曲"?

在数组中添加一个堆栈对象的副本,这个琐碎的任务就是添加一个默认的构造函数,我一开始就不需要这个构造函数。

class Q : public CObject {
public:
   Q() {}
   Q(int i) {}
};

void OnStart()
{
   CArrayObj ar;
   Q q(3);
   
   Q *new_el = new Q;
   new_el = q;
   ar.Add(new_el);
   Q new_el2(5);
   q = new_el2;
}

这不是致命的,是的,你可以在Q处做init(),这将使问题变得平滑一些,但仍然很恶心。而在手头复制auto_ptr时,一切都在两行中发生,但游戏并不值得去做。也许太挑剔了,完美主义。

 
pavlick_:

将一个堆栈对象的副本添加到一个数组中的琐碎任务变成了这样+我需要规定一个默认的构造函数,而我根本不需要。

这不是致命的,是的,你可以在Q处做init(),这将使问题变得平滑一些,但它仍然令人作呕。而在手头复制auto_ptr时,一切都在两行中发生,但游戏并不值得去做。也许太挑剔了,完美主义。

但在C++中也是完全一样的,所以并不清楚为什么会出现弯曲的mcl。

而在你的情况下,指定复制构造函数,用一行来添加元素会更容易。

ar.Add(new Q(q));
 
pavlick_:

将一个堆栈对象的副本添加到数组中的琐碎任务变成了这样+我需要写一个默认的构造函数,我根本不需要。

不是致命的,是的,你可以在Q处做init(),这样会使问题平稳一些,但还是很恶心的。而当你有复制auto_ptr时,一切都在两行中发生,但游戏并不值得去做。也许太挑剔了,完美主义。

反正都是这样的--它只是隐藏在你的auto_ptr后面......

我不认为这里有什么特别的问题。

作为一个顽固的老前辈,我真的不喜欢C#的做法,即自动删除内存。在我看来,应该由要求删除对象的人负责,而不是由一些 "垃圾收集者 "负责。

 
Alexey Navoykov:

但在C++中是完全一样的,所以并不十分清楚为什么mcl是歪的。

而在你的情况下,指定一个复制构造函数,并在一行中添加元素更容易。

怎么会一样呢?那里有一个自动的复制构造器,所有的操作都会有一个样子。

class Q : public CObject {
public:
   Q(int i) {}
};

void OnStart()
{
   CArrayObj ar;
   Q q(3);
   
   ar.Add(new(q));
   q = Q(5);
}

而在你的情况下,设置复制构造函数和添加元素只需一行就可以了

当然,这是一个玩具类的例子,在现实中也是一些数据,可能是很多,写一个复制的构造函数根本就不是一个办法。在包装器中包裹了正确的地方,不需要自定义构造器。

所以这一切还是会发生的--它只是隐藏在你的auto_ptr后面...

我不认为这里有什么特别的问题。

作为一个老顽固,我不喜欢C#的做法,即内存被自动删除。在我看来,要求删除对象的人应该对此负责,而不是一些垃圾收集者。

在μl中,你可以不使用智能指针。垃圾收集器!=智能指针,你不能没有它们,至少因为有例外情况。我自己不喜欢收集垃圾的人。