Exceptional C++ 读书笔记

More Exceptional C++ 读书笔记 More Exceptional C++ 读书笔记 Item 1 Switching Streams (1): 多考虑易读性,避免编写过渡简洁但是不易懂,不易维护的代码;    记个相当简洁的流切换代码:  (argc > 2 ? ofstream(argv[2], ios::out|ios::binary) : cout ) 1 ? ifstream(argv[1],      ios 阅读详情

Exceptional C++ 读书笔记


 //内存管理的一部分来自于http://blog.youkuaiyun.com/kingofark/category/9109.aspx

 Item 1 Iterator:
   
 (1): 注意当前迭代器是否有效,如果无效则解引用产生程序错误;
 (2):注意当前迭代器生命期,某些容器经过某些操作后将重新分配内部存储空间,则当前迭代器无效;
 (3) : 有效范围, 类似find(first, last, value)时, 迭代器first 必须在last之前,必须保证指向同一个容器;
       (4): 有效的内部操作;


 Item 2, 3: Case-Insensitive String
     
 (1) 1 关于std::string: std::string实际是
  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
  class basic_string;

  typedef basic_string<char> string;

  要实现case-insensitive string需要改变string的compare方式,因为char_traits<char>类提供compare等方式,所以
  就需要对char_traits<char>作相应的变动;
  char_traits::eq()和lt()提供相等和小于的对比方式,compare()和find()提供对比和搜索字符串序列的功能;更改这四个成员函数  就可以实现case-insensitive string;

 (2)关于实际应用中,最好选用一个单一的函数去接受两个相应的std::string对象,而非用更改traits的方法来实现一个ci_string;
 例如 bool CaseInsensitiveString(std::string &a, std::string &b)

 (3)类似ci_char_traits : public char_traits<char>, 用于变换traits或者iterator功能等情形,而非当作传统的OO方式来使用时,可以当作合理的派生,不必考虑virtual destructor等;

 

 Item 4, 5 Max Reusable Generic Containers

 (1) template constructor永远不会是一个copy constructor, 因为永远存在一个最适合的copy constructor, 因此overload resolution决不会将template constructor 当作copy constructor
 
 (2) 善于使用模板成员函数


 Item 6, 7 Temporary Objects
 
 (1) a: 用传递const T& 代替传值;
         b: 用预先创建的对象代替不需要的重复创建的对象,类似(container.end()每次被调用将返回一个临时的对象,这是不必要的);
     c: 用++T 代替 T++ (因为T++ 一般先制造一个临时对象,然后更新本身,最后返回临时对象);
         d: 用++T来实现T++;
     e: 避免做无用的隐式转换;
 
 (2) 注意对象生命期,绝不准让函数返回一个函数内部的auto变量的指针或者引用;

 (3) 多用标准库的代码;


 Item 8 -- 17 Writing Exception-Safe Code

 (1)当一个函数不能处理内部的异常时,应当将它抛给函数调用者去处理;
 (2) 当异常出现时,请让资源正确的被释放,数据处于一个稳定的状态;
 (3)绝不能让从destructor或者被重载的delete中抛出,写析构函数和资源分配函数时应当写上throw(); 
 (4)先将所有可能抛出异常的操作和安全的的操作分离出来,当可能抛出异常的操作执行成功时,再用no throw操作改变对象状态;
 (5)让每一个代码片段(类,模块,函数)负责单一的任务,类似STL stack中的pop和top是分离的
 
 (6): exception-safe基本准则:

  A: 基本安全: 当异常抛出时不产生资源泄漏;
  B: 健壮的安全性:如果某个操作因为异常的抛出而终止,则对象当前状态不应改变;
  C: 不抛出异常: 约定这个函数决不抛出异常;

 
 (7): 将资源管理单独的封装成一个类类似书上的例子 StackImpl封装了内存管理功能
 (8): 多用聚合,少用继承(包括这种聚合 pivate继承 -- 因为这将导致在constructor中无法控制base class

 (9): 用资源申请既初始化来隔离类的实现和资源的管理与所有权
 
 (10): 什么时候应当用private继承代替containment?
  a: 需要存取某个类的protected成员
  b: 需要覆写虚函数
  c: base 对象需要在其他类对象建构之前建构

 (11): 析构函数中决不允许抛出异常:
  a: 对象本身所申请的的资源不能完全释放;
  b:考虑 T t[20];的情况;析构某个T时抛出异常会产生未定义情况
  


 Item 18, 19 Code Complexity

 (1): 提供强异常安全需要损失一定程度的性能;
 (2): 如果一个函数存在几个不相关的副作用,那么它不可能实现异常安全, 否则应当把这几个函数分割为不同的函数
 (3): 不是所有的函数都需要强异常安全;


 Item 20 Class Mechanics
 (1): 设计时首先考虑标准库是否存在相关的类
 (2):  用explicit constructor代替隐式转换
 (3): 如果提供一个常规的operator op(类似+),那么应该同样提供一个operator op=(+=),
  operator op(类似的 + - * /)不应该改变对象值, 它应当返回一个 + 操作后的临时对象;
 (4): 多用a op= b 代替 a = a op b; 一般 const T operator op(T, T)产生一个临时变量;
 
 (5)  一元运算符是成员函数
       =,(),[]和->必须是成员函数
       +=,-=,/=,*=(等等)是成员函数
       所有其它的二元运算符是非成员函数

 (6) ++T 应当返回一个引用, T++应当返回一个const T,以防止 T++++这种情况发生;T++应当由++T来实现;
 (7) 避免使用前导下划线来命名,前导下划线是留给编译器使用的
 

 Item 21 override 虚函数 
 (1): 除非确定某个类不被派生,否则都应当提供一个虚函数;
 (2): 关于 overload, override和 hide
  a: overload意思是提供一个相同名称但是不同参数的函数, 编译时由编译器决定哪个是最匹配的函数
  b: override意思是在派生类提供一个相同名称且相同参数不同实现的虚函数,动态调用时将从派生类指针调用这个函数
  c: hide 某个函数的意思是有一个函数在某个范围内(派生类,嵌套类,名称空间等),隐藏同名函数
  
 (3) 当派生类提供一个和基类的某个成员函数同名的函数时,如果你不想隐藏基类的同名函数,请在派生类声明基类的同名函数,
  例如: using Base::f;
 (4) 永远不要在派生类override virtual function中改变默认参数;
 

 Item 22, 23 Class Relationships
 (1): 什么时候不应该选用public 继承
      a: 如果某个类为提供虚函数,这个类本身不打算实施多态;
      b: 如果某个类未提供protected 成员
      c: 类型为不是IS-A, WORKS-LIKE-A or USABLE-AS-A;
      d: 派生类只用了基类的public 成员;

 (2): 只有当需要存取某个类protected 成员或者override 虚函数的时候才应该选用private继承;不是IS-A, WORKS-LIKE-A or
      USABLE-AS-A的时候决不应当用public 继承;
 
 (3): 避免提供public virtual function, 使用template method 设计模式代替;从算法中提取出那些每次都要进行的步骤,将其抽象出  来,只把一些因地制宜的细节通过virtual function 留给派生类来实现。
 (4): 应用compiler-firewall 方法隐藏实现细节,使用一个不透明的指针(指向一个声明但未定义的类
  (struct xxxImpl; xxxImpl *pimpl_)来存private 成员,包括状态变量和成员函数);
  例如: clas Map { private: struct MapImpl; MapImpl *pimpl_; };
 

 

 Item 24 Uses and Abuses of Inheritance
 (1): 多用聚合,(containment, composition, layering HAS-A, delegation),当关系模型为 IS-IMPLEMENTED-IN-TERMS-OF时,请多考虑聚合,最好不用继承;

 (2): 非public 继承的条件:
  a: 当需要override virtual function时候;
  b: 需要存取基类protected成员时候
  c: 需要保证初始化顺序的时候(基类必须建构在派生类之前,析构在派生类之后等情况);
  d: 需要某种多态的访问控制时;

 (3): 用public继承时应当避免的问题:
  a: 如果非public继承可以做,那么决不要用public继承;绝不能用public继承表述一个依据什么实现的关系模型;
  b: 绝不能用public继承表述一个 IS-ALMOST-A关系模型(类似正方形是一个矩形等关系模型);

 (4): 应当总是先确定 public继承关系模型为 IS-A或者WORKS-LIKE-A


 Item 25 Object-Oriented Programming
 略;

 Item 26-28 Minimizing Compile-Time Dependencies
 (1): 决不#include无用的头文件;
 (2): 当前向声明某个stream时候用<iosfwd>足够了;
 (3): 如果composition足够的话,决不能用继承;
 

 Item 29 Compilation Firewalls
 (1): 放置所有的非virtual函数 private member 到Pimpl类中去; 客户程序员无论如何也不应当看到这些private成员;
      Pimpl类中某些函数可能需要类中某些成员的支持,所有需要一个back pointer指向类本身,back pointer通常命名为self_
 
 Item 30 The "Fast Pimpl" Idiom
 (1):绝不能放置对象到一个buffer里面,例如
  char buffer[100];
  new (&buffer[0]) T;
  a: 不能保证对齐规则;
  b: 脆弱
  c: 难于维护;
  

 
 Item 31 - 34 Name Lookup and Interface Principle
 (1): 对于一个class X,任何提及并且含有X(例如来自同一头文件或者名称空间)的函数(括成员函数,static函数和自由函数),逻辑上都属于class X的一部分,因为它们是X接口的一部分

  任何class X的成员函数都一定提及X;
  任何class X的成员函数都一定含有X(隐式的this);


  例如:
   class X{...};
   ostream& operator<<(ostream&, const X&)//肯定提及X;
   如果operator<<含有X ,例如在同一个头文件或者名称空间,那么它逻辑上属于X的一部分,因为他建构了X的一部分接口;
   否则反之;

  
 (2): 关于 supplied with;
  struct _iobuf{...};
  typedef struct _iobuf FILE;
  FILE* fopen(const char *filename, const char* mode);
  int fclose(FILE* stream);
  int fseek(FILE* stream, long offset, int origin);
  ......
  这些函数都是非成员,但是它们确实是 FILE接口的一部分;(part of the interface of FILE);

  class File
  {
  public:
   int fseek(long offset, int origin);
   ......
  };

  int fseek(FILE* stream, long offset, int origin);
  例如上例: int fseek(FILE* stream, long offset, int origin);
  提及并且同File都来自于头一个头文件或者名称空间,此函数一样属于File接口的一部分;

 
 (3):如果在某个作用域内调用了一个接受另一个作用域内类型参数的函数,那么编译器不止在当前作拥域内查找该函数,同时也会到接受的的  类型所在的作用域去查找该函数,而且不用特别声明;类似
  void f()
  {
   std:string hello = "hello world";
   std::cout  <<  hello;   //正确调用std::operator<<;
  }
  如果没有Koenig lookup,则编译器无法查找到operator<<是哪一个我们想要的;(这个函数封装在std::string内,是string接口的  一部分);如果希望正确调用的operator<<,我们需要 std::operator<<(std::cout, hello);
  
  所以,如果在同一个名称空间内定义了一个类和一个提及这个类的函数, 那么编译器将强制关联这个类和这个自由函数;

 (4): namespace A { class X {};  void f(X x) {} }
  namespace B { void f(A::X x) {} void g(A:: xx) { f(xx); } }
  这将导致B::g出现二义性而无法编译;原因在于g涉及A::X,所以编译时编译器同样将名称空间A内的函数也考虑进来,此时出现两个参  数为A::X的函数f

  类的成员函数将被优先考虑,例如
  namespace A { class X {};  void f(X x) {} }
  class B
  {
   void f(A::X x) {}
   void g(A:: xx) { f(xx); } //此时不会出现二义性问题;
  };
  如果编译器发现一个类成员函数为f(A::X),则不再使用Koenig lookup去搜索自由函数;
  

 (5):结论为名称空间不像想象的那样完全隔离函数声明,它只能属于部分独立;
 
 
 (6): 根据Interface Principle,如果一个函数提及了两个类,class X和class Y, 并且此函数同X包含在同一个名称空间或者头文件之中,那么,首先,此函数逻辑上是X的界面接口的一部分;由于此函数依赖Y,因此,X同样依赖于Y;

 (7): 如果A,B是类,f(A,B)是自由函数, 那么
  a: 如果A和f在同一头文件或名称空间内,那么f逻辑上是A的一部分,所以,A也依赖于B;
  b: 如果A,B和f在同一头文件或名称空间内,那么f逻辑上是A的一部分也是B的一部分,故此,A,B互相依赖;
 
  如果 ,A,B是类,A::g(B)是一个A的成员函数,那么:
  a: 因为A::g(B),所以,A,依赖于B;
  b:如果A,B被声明在一起(同一个头文件或名称空间),那么A,B互相依赖,A::g(B)逻辑上同样属于B的一部分;
  实际上,上述情况的实际含义是,类型A,B通常将被放在一起使用,,如果修改了一个,那么将影响另一个;

 (8):关于名称隐藏:
  struct B
  {
   int f(int);
   int f(double);
   int g(int);
  };

  struct D : public B
  {
  private:
   int g(std::string, bool);
  };

  D d;
  int i;
  d.f(i)  //调用B::f(int);
  d.g(i); //错误,提示应当提供两个参数;
  
   实际上,编译器查找匹配函数名称时候,先查找当前范围内的名称匹配函数,例如这里是D,然后列出一个编译器所能找到的函  数名称 相同的函数的列表,但是并不考虑存取权限和所携带参数是否正确,如果它一个名称匹配的函数都没找到的话,那么将向外一层  继续查找,如果编译器找到一个或者多个候选的函数,编译器将停止查找,然后提交函数的重载决议;
  两种解决方法是
  a: d.B::g(i);//编译器自然会考虑B的范围;
  b:
   struct D : public B
   {
   using B::g;
   private:
    int g(std::string, bool);
   };

  
  
  

 (9): 使用名称空间,如果写一个类在名称空间N中,那么请将所有的协助函数和操作符都都写在N中;

 

 Item 35, 36 Memory Management
 
 (1):

  [常量数据(const data)区:]
  常量数据区存储字符串等在编译期间就能确定的值。类对象不能存在于这个区域中。在程序的整个生存周期内,区域中的数据都是可  用的。区域内所有的数据都是只读的,任何企图修改本区域数据的行为都会造成无法预料的后果。之所以会如此,是因为在实际的实现  当中,即使是最底层的内部存储格式也受制于所实现的特定的优化方案。例如,一种编译器完全可以把字符串存放在几个重叠的对象里  面——只要实现者愿意的话。 

  [栈(stack)区:]
  栈区存储自动变量(automatic variables)。一般来说,栈区的分配操作要比动态存储区(比如堆(heap)或者自由存储区(free   store))快得多,这是因为栈区的分配只涉及到一个指针的递增,而动态存储区的分配涉及到较为复杂的管理机制。栈区中,内存一  旦被分配,对象就立即被构造好了;对象一旦被销毁,分配的内存也立即被收回(译注:这里作者用了“去配(deallocate)”一词,  鄙人一律翻译为“回收”)。因此,在栈区中,程序员没有办法直接操纵那些已经被分配但还没有被初始化的栈空间(当然,那些通过  使用显式(explicit)析构函数(destructor)和new运算符而故意这么做的情况不算在内)。

  [自由存储区(free store):]
    自由存储区(free store)是C++两个动态内存区域之一,使用new和delete来予以分配和释放(freed)。在自由存储区(free    store)中,对象的生存周期可以比存放它的内存区的生存周期短;这也就是说,我们可以获得一片内存区而不用马上对其进行初始  化;同时,在对象被销毁之后,也不用马上收回其占用的内存区。在对象被销毁而其占用的内存区还未被收回的这段时间内,我们可以  通过void*型的指针访问这片区域,但是其原始对象的非静态成员以及成员函数(即使我们知道了它们的地址)都不能被访问或者操  纵。
  
  [堆(heap)区:]
  堆(heap)区是另一个动态存储区域,使用malloc、free以及一些相关变量来进行分配和回收。要注意,虽然在特定的编译器里缺省的  全局运 算符new和delete也许会按照malloc和free的方式来被实现,但是堆(heap)与自由存储区(free store)是不同的——在某  一个区域内被分配的内存不可能在另一个区域内被安全的回收。堆(heap)中被分配的内存一般用于存放在使用new的构造过程中和显  式(explicit)的析构过程中涉及到的类对象。堆中对象的生存周期与自由存储区(free store)中的类似。

  [全局/静态区(Global/Static):]
     全局的或静态的变量和对象所占用的内存区域在程序启动(startup)的时候才被分配,而且可能直到程序开始执行的时候才被初始  化。比如,函数中的静态变量就是在程序第一次执行到定义该变量的代码时才被初始化的。对那些跨越了翻译单元(translation    unit)的全局变量进行初始化操作的顺序是没有被明确定义的,因而需要特别注意管理全局对象(包括静态类对象)之间的依赖关系。  最后,和前面讲的一样,全局/静态区(Global/Static)中没有被初始化的对象存储区域可以通过void*来被访问和操纵,但是只要是  在对象真正的生存周期之外,非静态成员和成员函数是无法被使用或者引用的。

  

  [关于“堆(heap)vs.自由存储区(free store)”]:
  本条款中我们将堆(heap)和自由存储区(free store)区分开来,是因为在C++标准草案中,关于这两种区域是否有联系的问题一直  很谨慎的没有予以详细说明。比如当内存在通过delete运算符进行回收时,18.4.1.1中说道:
   It is unspecified under what conditions part or all of such reclaimed storage is allocated by a     subsequent call to operator new or any of calloc, malloc, or realloc, declared in <cstdlib>.

   [关于在何种情况下,这种内存区域的部分或全部才会通过后续的对new(或者是在<cstdlib>里声明的calloc,malloc,    realloc中的任何一个)的调用来被分配的问题,在此不作详细规定,不予详述。]

 

       同样,在一个特定的实现中,到底new和delete是按照malloc和free来实现的,或者反过来malloc和free是按照new和delete来实现  的,这也没有定论。简单地说吧,这两种内存区域运作方式不一样,访问方式也不一样——所以嘛,当然应该被当成不一样的两个东西  来使用了!

 

 Item 37: AUTO_PTR
  略

 Item 38 Object Identity

 (1): 千万别写一个依赖于检测自身赋值达到正确操作的operator=(),一个拷贝赋值操作符应当使用create-a-temporary-and-swap
  方法来自动维持强异常安全和安全的自身赋值;
 
 (2): 自身赋值是个可行的优化去避免无用的工作;

 

 Item 39 Automatic Conversions
 
 (1): 避免使用隐式转换操作符:
  a: 隐式转换会影响重载决议;
  b: 隐式转换会让错误的代码安静的编译通过;

 (2): C++标准保证「对指向同一个对象的多个指针的比较之结果必须是“相等(equal)” 」,但却并不保证「对指向不同对象的多个指针  的比较之结果必须是“不相等(unequal)”」。

 Item 40,41 Object Lifetimes
 
 (1): void f()
  {
   T t(1);
   T& rt = t;
   //#1  do something;
   t.~T();
   new (&t) T(2);
   //#2  do something;
  };

 a: #2是合法的;
 b: #2是不安全的;

 请总是尝试写异常安全级别的代码, 总是尝试正确的组织代码让资源正确的申请和释放当异常抛出时;

 
 (2): 避免C++ 语言级别定义不太明确的技巧,应该多用清晰简单的编程技巧;   

 (3): 用同一个成员函数完成两种拷贝操作(拷贝构造和拷贝赋值)的注意是很好的:这意味着我们只需在一个地方编写和维护操作代码。本条  款问题中的惯用法只不过是选择了错误的函数来做这件事。如此而已。

 

  其实,惯用法应该是反过来实现的:拷贝构造操作应该以拷贝赋值操作来实现,不是反过来实现。例如:

  T::T( const T& other ) {
        /* T:: */ operator=( other );
  }
      
  T& T::operator=( const T& other ) {
        // 真正的工作在这里进行
        // (大概可以在异常安全的状态下完成,但现在
        // 其可以抛出异常,却不会像原来那样产生什么不良影响
         return *this;
      }
  这段代码拥有原惯用法的所有益处,却不存在任何原惯用法中存在的问题。[注5] 为了代码的美观,你或许还要编写一个常见的私有辅  助函数,利用其做真正的工作;但这也是一样的,无甚区别:

      T::T( const T& other ) {
        do_copy( other );
      }
      
  T& T::operator=( const T& other ) {
        do_copy( other );
        return *this;
      }
      
  T& T::do_copy( const T& other ) {
        // 真正的工作在这里进行
        // (大概可以在异常安全的状态下完成,但现在
        // 其可以抛出异常,却不会像原来那样产生什么不良影响
  }

 

 


  如果需要的话,请编写一个私有函数来使拷贝操作和拷贝赋值共享代码;千万不要利用「使用显式的析构函数并且后跟一个placement   new」的方法来达到「以拷贝构造操作实现拷贝赋值操作」这样的目的,即使这个所谓的技巧会每隔三个月就在新闻组中出现几次。  (也就是说,决不要编写如下的代码:)

         T& T::operator=( const T& other )
         {
             if( this != &other)
             {
                  this->~T();             // 有害!
                  new (this) T( other );  // 有害!
             }
             return *this;
         }

 


 Item 42: Variable Initialization -- Or is it?

 (1): 关于 T u; T t = u;
  这时,编译器总会是调用 copy-construct而不是调用默认constructor之后调用operator=(),这只是一个从C继承来的语法,   并没有赋值操作

 (2): 用 T t(u);代替 T t = u;


 Item 43 Const-Correctiness;

 (1): 避免在某个函数参数使用 const by value
 (2): 如果是非内部类型的return by value,那么优先考虑返回一个const value;
 (3): 如果某个类数据成员的改变并不影响到类状态的改变,例如class X { private: char buffer[1024]; ...};
  那么当某函数只改变这个类数据成员,而不改变其他成员时,也应当把这个函数为const ,并将这个被改变但无关类状态的成员声明为
  mutable;


 Item 44 Casts

 (1): 请优先使用新转型风格cast;

 (2): 避免用const_cast消除const ,请优先使用mutable;

 (3): 避免动态的向下转型;

 Item 45: BOOL
 略

 Item 46 Forwarding Functions;

 (1): 多考虑传递对象的const &;
 (2): 避免语言的隐晦角落,多用简单的技巧;
 (3): 如果不认为性能上绝对需要,请避免inline或者内部优化;


 Item 47 Control Flow

 (1): 避免使用全局或者静态变量;如果必须如此,那么请注意它们的初始化顺序(因为多个头文件内引入的静态变量的声明顺寻并不是标准定  义的);

 (2): 将基类的constructor在初始化器列表中的顺序和类声明的顺序是一样的,基类的初始化顺序是依据类定义时的顺序的;

 (3): 将类的数据成员的初始化顺序与初始化器列表中声明的顺序是一样的,同样依据类定义;

 (4): 努力去实现代码的异常级安全;

 (5): 绝不能写依赖函数参数赋值顺序的代码;
 

PyTorch实战:5步搞定Res2Net图像分类模型(附完整代码) 本文详细介绍了如何使用PyTorch在5步内构建高性能Res2Net图像分类模型,包括环境配置、核心模块实现、完整网络架构搭建、训练流程优化及模型部署技巧。Res2Net通过多尺度特征融合机制显著提升图像分类性能,附完整代码帮助开发者快速实践。 阅读详情

相关推荐

全国大学校园网—拓扑图欣赏

全国大学网络拓扑图(一百张) 典型十张 1、 中央财经大学 2、国防科技大学 3、济南大学 4、西安石油大学 5、南通大学IPV6网络 6、中国矿业大学 7、青海师范大学 8、内蒙古科技大学 9、三峡大学 10、中共江苏省党校 剩余90张 点赞、评论获取 ...

LiBai'S BLOG 5万+

More Exceptional C++ 读书笔记2

//内存管理的一部分来自于http://blog.youkuaiyun.com/kingofark/category/9109.aspx Item 1 Iterator:  (1): 注意当前迭代器是否有效,如果无效则解引用产生程序错误; (2):注意当前迭代器生命期,某些容器经过某些操作后将重新分配内部存储空间,则当前迭代器无效; (3) : 有效范围, 类似find(first, last

小飞侠 778

【STM32】R05D电控红外协议的美的空调遥控器

目录一、设计思路一、R05D红外协议原理1.协议手册理解2.验证时序(重点)二、硬件实现1.需要的材料2.对发射模块电路进行修改3.STM32 GPIO选择三、代码实现1.载波38kHZ实现2.R05D时序实现3.调用函数并验证 一、设计思路 通常红外遥控采用NEC传输协议,而美的空调采用的是R05D红外协议(应该是自己设计的协议),因此用一般红外编码发射模块无法直接对空调进行控制。 解决方法:获取R05D协议手册 + 用红外接收管对原有遥控器红外接收进行波形分析。 一、R05D红外协议原理 R05D电控功

weixin_42204837的博客 1万+

Exceptional C++ 笔记

1、 使用常引用const & 代替值传递 2、 使用先增操作,避免使用后增操作:在进行后增操作时,对象不但需要自增,还要返回一个包含自增前值得临时对象。 3、 遵循‘单入口/单出口’原则,绝不要在一个函数里面写有多个return语句。 4、 绝对不要返回对局部对象的引用!!! 5、 尽量使用标准库算法 6、 优先采用 "a opt= b" 这样的写法, 而不是 "a...

qq_32619837的博客 358

细说VLAN之untag和tag

一、拓扑图 先给出上面拓扑图的结论,后面再详细讲解: 结论:只有PC1与PC4之间能相互通信,除此之外,所有PC之间均不能通信,比如PC1与PC3不能建立通信。 针对Ping命令的一个知识: 要想ping通某台主机,必须满足两个条件: 1,源主机的ICMP请求包必须能达到目的主机。 2,目的主机的ICMP应答包必须能回到源主机。 二、理论基础 端口的出...

NoobMaster的博客 3万+

LT9211 单路mipi转双路mipi芯片,方案成熟,提供技术支持

LT9211 单路mipi转双路mipi芯片

TEL15012949045的博客 5016

记下最近看Exceptional C++的一些感受和疑问

1.苦于平时使用标准模板库的时间不多,对标准模板库的经验很少,所以还没有什么太多的感受不过不论是哪本关于C++标准库的书籍,都会强调一定不能使用无效的迭代器以及某些操作过后会使得迭代器失效! 2.实现大小写不敏感字符串的方法中继承了char_traitstraits的概念还是没有完全掌握,或者说应该抽时间实作一下才能更好理解 3.因为C++程序员总是把效率挂在嘴边,总是为了效率

侯杰 的专栏 1251

100G SR4 光模块设计

目前100G SR4 光模块主要采用COB 封装技术,在光电芯片键合(bonding)阶段,首先使用银胶将光芯片、电芯片精准固定在电路板规定位置上,该工序即为元件键合(die bonding);然后采用打线机进行金线键合(wire bonding),完成光模块内部的电气连接。在光路耦合阶段,采用8路阵列透镜组完成光路90°弯折及聚焦,并采用有源耦合的工艺进行光路的最终确认,该设计方案工艺简单、高效,借助全自动贴片机、打线机和耦合台就可实现100G SR4 光模块的大批量生产。

Flyin_Group的博客 1373

exceptional c++读书笔记

xx

onlyForCloud的专栏 494

基于 YOLOv26 的食品包装缺陷检测系统:智能视觉质检方案

本文提出了一种基于YOLOv26深度学习的食品包装缺陷智能检测系统。该系统能够自动识别多种常见包装缺陷,包括密封不良、破损、污染、标签错误等8类问题。相比传统人工检测方法,该系统具有高精度、多类别分类、实时推理等优势。文章详细介绍了系统架构,包含数据采集、预处理、YOLOv26检测模型和后处理四个核心模块,并提供了完整的环境配置和数据处理代码实现。该系统为食品包装行业提供了一种高效、准确的智能视觉质检解决方案。

一键难忘的博客 683

2026年1至9月武汉市房地产价格深度分析报告

本报告基于2026年1月至9月武汉市实际成交案例,从成交价格、区域分布、户型结构、价格走势等维度进行深度分析。数据来源包括武汉市住房保障和房屋管理局备案数据、主要中介机构成交记录及典型楼盘网签案例,覆盖全市15个行政区及主要功能板块。

王国平的博客 327

more exceptional c++读书笔记

Part1 我是在读完Scott Meyers的《Effective c++》之后才读到这本书的。能够讨论特定的主题而不是将一门语言作为一个整体来看待是我理解c++的首选方式,所以Sutter和Meyers的书非常适合我。 与Meyers系列相比,exception c++系列的主要优势在于,您可以告诉Sutter是更好的程序员。你可以相信Meyers 所说的一切都是正确的,但最终你真正得到的只是一些关于如何做某些事情的额外指示。另一方面,Sutter在同样的主题上讲得更深入一些,让你觉得自己可以写出更

itaoest的博客 413

基于STM32、HAL库的MCP4651-503E/ST数字电位器驱动程序设计

@param channel: 通道 (0: A通道, 1: B通道)* @param channel: 通道 (0: A通道, 1: B通道)// SPI1 SCK/MISO/MOSI引脚配置。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hmcp: MCP4651句柄。* @param hspi: SPI句柄。

corlin6688的博客 137

《More Exceptional C++》读书笔记

2013.4.9 1.对象的生命周期。 开始:构造函数执行完毕并正常返回之时。 如果构造函数不成功,析构函数永远不会被调用。 结束:析构函数开始执行之时。 在生命周期开始之前和生命周期结束之后,对象的状态都是没有存在。 2构造函数的异常抛出。 只要在初始化列表中的基类和成员子对象的构造函数抛出异常,就一定会从它们的外层构造函数中抛出,无法阻止。 析造函数不应抛出异常?

小庞(android/java/PHP/Web/linux/mysql) 750

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

《Exceptional C++ Style》读书笔记

第1条 vector的使用   访问vector的元素 这个知识点主要是讲用[]和at访问vector元素的区别。大致的意思是,如果[]的话,因为标准并没有要求它做范围检查,所以效率较高,但访问越界不会抛出异常;如果是用at的话,因为其内部有范围检查,所以越界时会抛出异常。 下面是VS2005中的代码,请参考:     reference at(size_type _Pos)

backard的专栏 954

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Exceptional C++ 中文版 读书笔记

1.vector::iterator last = find(e.begin(),e.end(),"12/31/95");  *last = "12/30/95";可能出现的错误:如果find没有找到"12/31/95"迭代器讲返回第二个参数e.end(),而e.end()指向最后一个元素的下一个位置,对这个返回的值解引用和赋值是错误的2.copy(first,last,ostream_iterator(cout,"/n"));可能出现的错误:first在容器中指向的对象要求在last后面,否则这就不是一个

红黑的米兰的专栏 690

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

exceptional c++ 读书笔记 一 . vector 的使用

一. at() 与 operator[] void f(vector<int>& v) { v[0]; v.at(0); } 对于 vector 中的元素的随机访问有两种方式operator[] 和 at() , 两种方式的区别主要就是 at() 函数会进行边界检查,对于越界会抛出异常std::out_of_range...

weixin_30793643的博客 83

读书笔记之:Exceptional C++ Style (2004) [++]

1. vector中元素的访问:[]与at操作 2. 调整vector的大小:reserve reserve是保证vector的容量至少为某个值,它不会减少vector的容量。 resize是改变vector的大小,这个操作比较严格,给出多少,结果vector的容量就变为多少。 3. sprint的替代方案 4. 定位new表达式 5. 模...

weixin_33935505的博客 148

读书笔记之:More Exceptional C++ (2002) [++]

1. std::cin和std::cout的类型是什么? 简单的回答,cin实际上是: std::basic_istream<char,std::char_traits<char>> cout实际上是: std::basic_ostream<char,std::char_traits<char>> 首先,cin和cout具有的类型...

weixin_33957648的博客 129

Exceptional C++读书笔记:编译器防火墙与Pimpl惯用法(一)

Exceptional C++第四章主要介绍如何降低编译期文件依赖性以及常用的Pimpl用法。 方法一:不要用#include指令包含一些不必要的头文件,因为这样会严重降低编译效率,增加编译时间。 如下程序片段: 1.可以去掉iostream 因为根据代码,只需要ostream即可,况且已经包含进来ostream的头文件2.用#include代替#include 两处用到ostreamde

随便写写........... 569

C++ Exceptional 重载运算符new和delete时要注意的地方

首先看下面一段代码,找出代码中存在的问题:class B { public: virtual ~B(); void operator delete(void*, size_t) throw(); void operator delete[](void*, size_t) throw(); void f(void*, size_t) throw(); };class D

chpeui的专栏 533
上一篇: 一个人的战争 (1) : Bencoding格式解码
下一篇: More Exceptional C++ 读书笔记
SolidusSnake
博客等级 码龄20年 1粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值