当前位置: 首页 > 编程日记 > 正文

C++中模板的使用

模板(Template)指C++程序设计语言中的函数模板与类模板,是一种参数化类型机制。模板是C++泛型编程中不可缺少的一部分。

C++ templates enable you to define a family of functions or classes that can operate on different types of information.

模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码可重用性。

模板的声明与定义:模板定义以关键字template开始,后接模板形参表(template parameter list),模板形参表是用尖括号括住的一个或者多个模板形参的列表,形参之间以逗号分隔。模板形参可以是表示类型的类型形参(type parameter),也可以是表示常量表达式的非类型形参(non-type parameter)。非类型形参跟在类型说明符之后声明。类型形参跟在关键字class或typename之后声明。模板形参可以给出默认值(default arguments for template parameters)。

模板的非类型形参(template non-type parameter)允许为以下形式:(1)、整型或枚举型;(2)、到对象的指针或函数指针;(3)、到对象的引用或函数引用;(4)、成员指针。

模板的非类型参数被声明为数组或函数的,将被转换为指针或函数指针。模板的非类型形参允许用const或volatile限定(而模板的类型形参是不允许用const或volatile限定的)。模板的非类型形参是不允许声明为浮点型、class类型、void型。

模板的模板参数:类模板的模板参数允许是另外一个类模板,这称为模板的模板参数(template template parameter),也译作“模板参数模板”。函数模板不允许有模板的模板参数。

模板参数的默认值:模板形参可以给出默认值(default arguments for template parameters)。如果一个模板参数给出了默认值,那么模板形参列表中在其后声明的模板参数都应该给出默认值。

一个模板的各次声明给出的模板参数的默认值可以累积其效果。模板参数的作用域为从其声明之处至该模板的定义结束之处。因此可以使用一个模板参数作为其后声明的其他模板参数的一部分或默认值。

模板的使用:使用模板时,可以在模板名字后面显式给出用尖括号括住的模板实参列表(template argument list)。对模板函数或类的模板成员函数,也可不显式给出模板实参,而是由编译器根据函数调用的上下文推导出模板实参,这称为模板参数推导。

如果模板参数使用其默认值,则在模板实参列表中可以忽略它。如果所有的模板参数都使用了默认值,模板实参列表为空,但仍然必须写出成对的尖括号。

对于作为类型的模板实参,不允许是局部类型(local type)、无链接性的类型(type with no linkage)、无名类型(unnamed type)或包括了这三种情形的复合类型。但C++11以允许本地类型作为模板实参。

模板的嵌套:成员模板,对于类中的模板成员函数、嵌套的成员类模板,可以在封闭类的内部或外部定义它们。当模板成员函数、嵌套类模板在其封闭类的外部定义时,必须以封闭类模板的模板参数(如果它们也是模板类)和成员模板的模板参数开头。C++标准规定:如果外围的类模板没有特例化,里面的成员模板就不能特例化。

依赖名字与typename关键字:一个模板中的依赖于一个模板参数(template parameter)的名字被称为依赖名字(dependent name)。当一个依赖名字嵌套在一个类的内部时,称为嵌套依赖名字(nested dependent name)。一个不依赖于任何模板参数的名字,称为非依赖名字(non-dependent name)。

编译器在处理模板定义时,可能并不确定依赖名字表示一个类型,还是嵌套类的成员,还是类的静态成员。C++标准规定:如果解析器在一个模板中遇到一个嵌套依赖名字,它假定那个名字不是一个类型,除非显式用typename关键字前置修饰该名字。

typename关键字有两个用途:(1)、常见的在模板定义中的模板形参列表,表示一个模板参数是类型参数。等同于使用class。(2)、使用模板类内定义的嵌套依赖类型名字时,显式指明这个名字是一个类型名。否则,这个名字会被理解为模板类的静态成员名。C++11起,这一用途也可以出现在模板以外,尽管此时typename关键字不是必要的。

在下述情形,对嵌套依赖类型名字不需要前置修饰typename关键字:(1)、派生类声明的基类列表中的基类标识符;(2)、成员初始化列表中的基类标识符;(3)、用class、struct、enum等关键字开始的类型标识符。因为它们的上下文已经指出这些标识符就是作为类型的名字。

template关键字有两个用途:(1)、常见的在模板定义的开始;(2)、模板类内部定义了模板成员函数或者嵌套的成员模板类。在模板中,当引用这样的模板成员函数或嵌套的成员模板类时,可以在::(作用域解析)运算符、.(以对象方式访问成员)运算符、->(以指针方式访问成员)运算符之后使用template关键字,随后才是模板成员函数名字或嵌套的成员模板类名字,这使得随后的左尖括号<被解释为模板参数列表的开始,而不是小于号运算符。C++11起,这一用途也可以出现在模板以外,尽管此时template关键字不是必要的。

模板实例化(template instantiation):是指在编译或链接时生成函数模板或类模板的具体实例源代码。ISO C++定义了两种模板实例化方法:隐式实例化(当使用实例化的模板时自动地在当前代码单元之前插入模板的实例化代码)、显式实例化(直接声明模板实例化)。在C++语言的不同实现中,模板编译模式(模板初始化的方法)大致可分为三种:

(1)、Borland模型(包含模板编译模式):编译器生成每个编译单元中遇到的所有的模板实例,并存放在相应的目标文件中;链接器合并相同的模板实例,生成可执行文件。为了在每次模板实例化时模板的定义都是可见的,模板的声明与定义放在同一个.h文件中。这种方法的优点是链接器只需要处理目标文件;这种方法的缺点是由于模板实例被重复编译,编译时间被加长了,而且不能使用系统的链接器,需重新设计链接器。

(2)、Cfront/查询模型(分离(Separation)模板编译模式):AT&T公司的C++编译器Cfront为解决模板实例化问题,增加了一个模板仓库,用以存放模板实例的代码并可被自动维护。当生成一个目标文件时,编译器把遇到的模板定义与当前可生成的模板实例存放到模板仓库中。链接时,链接器的包装程序(wrapper)首先调用编译器生成所有需要的且不在模板仓库中的模板实例。这种方法的优点是编译速度得到了优化,而且可以直接使用系统的链接器;这种方法的缺点是复杂度大大增加,更容易出错。使用这种模型的源程序通常把模板声明与非内联的模板成员分别放在.h文件与模板定义文件中,后者单独编译。

(3)、混合(迭代)模型:g++目前是基于Borland模型完成模板实例化。g++未来将实现混合模型的模板实例化,即编译器把编译单元中的模板定义与遇到的当前可实现的模板实例存放在相应的目标文件中;链接器的包装程序(wrapper)调用编译器生成所需的目前还没有实例化的模板实例;链接器合并所有相同的模板实例。使用这种模型的源程序通常把模板声明与非内联的模板成员分别放在.h文件与模板定义文件中,后者单独编译。

ISO C++标准规定,如果隐式实例化模板,则模板的成员函数一直到引用时才被实例化;如果显式实例化模板,则模板所有成员立即都被实例化,所以模板的声明与定义在此处都应该是可见的,而且在其它程序文本文件使用了这个模板实例时用编译器选项抑制模板隐式实例化,或者模板的定义部分是不可见的,或者使用template<> type FUN_NAME(type list)的语句声明模板的特化但不实例化。

关于模板实例化(template instantiation):

(1)、指在编译或链接时生成函数模板或类模板的具体实例源代码,即用使用模板时的实参类型替换模板类型参数(还有非类型参数和模板型参数);

(2)、隐式实例化(implicit instantiation):当使用实例化的模板时自动地在当前代码单元之前插入模板的实例化代码,模板的成员函数一直到引用时才被实例化;

(3)、显式实例化(explicit instantiation):直接声明模板实例化,模板所有成员立即都被实例化;

(4)、实例化也是一种特例化,被称为实例化的特例(instantiated(or generated) specialization)。

隐式实例化时,成员只有被引用到才会进行实例化,这被称为推迟实例化(lazy instantiation)。

模板实例化是生成采用特定模板参数组合的具体类或函数(实例)。例如,编译器生成一个采用Array<int>的类,另外生成一个采用Array<double>的类。通过用模板参数替换模板类定义中的模板参数,可以定义这些新的类。

关于模板的编译和链接:

(1)、包含模板编译模式:编译器生成每个编译单元中遇到的所有的模板实例,并存放在相应的目标文件中;链接器合并等价的模板实例,生成可执行文件,要求实例化时模板定义可见,不能使用系统链接器;

(2)、分离模板编译模式(使用export关键字):不重复生成模板实例,编译器设计要求高,可以使用系统链接器;

(3)、包含编译模式是主流,C++11已经弃用export关键字(对模板引入extern新用法),一般将模板的全部实现代码放在同一个头文件中并在用到模板的地方用#include包含头文件,以防止出现实例不一致。

关于template、typename、this关键字的使用:

(1)、依赖于模板参数(template parameter,形式参数,实参英文为argument)的名字被称为依赖名字(dependent name),C++标准规定,如果解析器在一个模板中遇到一个嵌套依赖名字,它假定那个名字不是一个类型,除非显式用typename关键字前置修饰该名字;

(2)、和上一条typename用法类似,template用于指明嵌套类型或函数为模板;

(3)、this用于指定查找基类中的成员(当基类是依赖模板参数的类模板实例时,由于实例化总是推迟,这时不依赖模板参数的名字不在基类中查找)。

C++11 关于模板的新特性:

(1)、”>>”根据上下文自动识别正确语义;

(2)、函数模板参数默认值;

(3)、变长模板参数(扩展sizeof…()获取参数个数);

(4)、模板别名(扩展using关键字);

(5)、外部模板实例(拓展extern关键字),弃用export template。

函数模板:模板(Templates)使得我们可以生成通用的函数,这些函数能够接受任意数据类型的参数,可返回任意类型的值,而不需要对所有可能的数据类型进行函数重载。这在一定程度上实现了宏(macro)的作用。模板函数也可以提前声明,不过声明时需要带上模板头。

函数模板描述了仅用参数或返回值的类型来区分的一组相关函数。对于函数模板,编译器不支持函数参数列表中非类型模板参数的表达式。

类模板(class templates):使得一个类可以有基于通用类型的成员,而不需要在类生成的时候定义具体的数据类型

模板特殊化(特例化,Templatespecialization):由以下格式定义:

template<> class class_name <type>

这个特殊化本身也是模板定义的一部分,因此,我们必须在该定义开头写template <>。而且因为它确实为一个具体类型的特殊定义,通用数据类型在这里不能够使用,所以第一对尖括号<>内必须为空。在类名称后面,我们必须将这个特殊化中使用的具体数据类型写在尖括号<>中。

当我们特殊化模板的一个数据类型的时候,同时还必须重新定义类的所有成员的特殊化实现。这样做的原因就是特殊化不会继承通用模板的任何一个成员。

所谓模板特例化即对于通例中的某种或某些情况做单独专门实现,最简单的情况是对每个模板参数指定一个具体值,这成为完全特例化(full specialization),另外,可以限制模板参数在一个范围取值或满足一定关系等,这称为部分特例化(partial specialization),用数学上集合的概念,通例模板参数所有可取的值组合构成全集U,完全特例化对U中某个元素进行专门定义,部分特例化对U的某个真子集进行专门定义。

关于模板特例化:

(1)、在定义模板特例之前必须已经有模板通例(primary template)的声明;

(2)、模板特例并不要求一定与通例有相同的接口,但为了方便使用(体会特例的语义)一般都相同;

(3)、匹配规则,在模板实例化时如果有模板通例、特例加起来多个模板版本可以匹配,则依据如下规则:对版本AB,如果A的模板参数取值集合是B的真子集,则优先匹配A,如果AB的模板参数取值集合是”交叉”关系(AB)交集不为空,且不为包含关系),则发生编译错误,对于函数模板,用函数重载分辨(overload resolution)规则和上述规则结合并优先匹配非模板函数。

从编译器的角度来看,模板不同于一般的函数或类。它们在需要时才被编译(compiled on demand),也就是说一个模板的代码直到需要生成一个对象的时候(instantiation)才被编译。当需要instantiation的时候,编译器根据模板为特定的调用数据类型生成一个特殊的函数。

测试代码如下:

template.hpp:

#ifndef FBC_MESSY_TEST_TEMPLATE_HPP_
#define FBC_MESSY_TEST_TEMPLATE_HPP_#include <vector>// reference: https://zh.wikipedia.org/wiki/%E6%A8%A1%E6%9D%BF_(C%2B%2B)
// 函数模板,此函数在编译时会自动产生对应参数类型的代码,而不用显式声明
template <typename T>
inline const T& maximum(const T& x, const T& y)
{if (y > x){return y;} else{return x;}
}// 类模板
template <typename Ty>
class ComPtr
{
protected:Ty* m_ptr;
public:ComPtr() {m_ptr = NULL;}ComPtr(const ComPtr& rhs) {m_ptr = NULL;SetComPtr(rhs.m_ptr);}ComPtr(Ty* p) {m_ptr = NULL;SetComPtr(p);}~ComPtr() {Release();}const ComPtr& operator=(const ComPtr& rhs) {SetComPtr(rhs.m_ptr);return *this;}Ty* operator=(Ty* p) {SetComPtr(p);return p;}operator Ty* () {return m_ptr;}Ty* operator->() {return m_ptr;}operator Ty** () {Release();return &m_ptr;}operator void** () {Release();return (void**)&m_ptr;}bool IsEmpty() {return (m_ptr == NULL);}void SetComPtr(Ty* p) {Release();m_ptr = p;if (m_ptr) {m_ptr->AddRef();}}void Release() {if (m_ptr) {m_ptr->Release();m_ptr = NULL;}}
};// 模板的嵌套:成员模板
template <typename C> class myc{
public:template <typename S> C foo(S s);
};//下行需要给出外部类与内部嵌套类的模板形参列表:
template<typename C> template <typename S> C myc<C>::foo(S s){C var;return var;
}// reference: http://www.tutorialspoint.com/cplusplus/cpp_templates.htm
// function template
template <typename T>
inline T const& Max(T const& a, T const& b)
{return a < b ? b : a;
}// class template
template <class T>
class Stack {
private:std::vector<T> elems; // elements public:void push(T const&); // push element void pop(); // pop element T top() const; // return top element bool empty() const{ // return true if empty.return elems.empty();}
};template <class T>
void Stack<T>::push(T const& elem)
{// append copy of passed element elems.push_back(elem);
}template <class T>
void Stack<T>::pop()
{if (elems.empty()) {throw fprintf(stderr, "Stack<>::pop(): empty stack\n");}// remove last element elems.pop_back();
}template <class T>
T Stack<T>::top() const
{if (elems.empty()) {throw fprintf(stderr, "Stack<>::top(): empty stack\n");}// return copy of last element return elems.back();
}// reference: http://www.prglab.com/cms/pages/c-tutorial/advanced-concepts/templates.php
// 模板特殊化(特例化,Template specialization)
template <class T> class pair {
private:T value1, value2;
public:pair(T first, T second){value1 = first;value2 = second;}T module() { return 0; }
};template <>
class pair <int> {
private:int value1, value2;
public:pair(int first, int second){value1 = first;value2 = second;}int module() { return value1 % value2; }
};template <class T> struct PrintType {};template<> struct PrintType <int> {const std::string type(){return "int type";}
};template<> struct PrintType <float> {const std::string type(){return "float type";}
};template<> struct PrintType <std::string> {const std::string type(){return "string type";}
};// 函数模板声明与定义分开
template <typename T>
inline const T& max_mum(const T& x, const T& y);// 类模板声明与定义分开
template<class T>
class A {
public:void f();
};void test_template1();
void test_template2();
void test_template3();
void test_template4();
void test_template5();
void test_template6();
void test_template7();#endif // FBC_MESSY_TEST_TEMPLATE_HPP_


template_impl.cpp:

#include <iostream>
#include "template.hpp"template <typename T>
const T& max_mum(const T& x, const T& y)
{if (y > x){return y;}else{return x;}
}// 函数模板声明与定义分开:函数模板显示实例化
template const int& max_mum<int>(const int&, const int&);template<class T>
void A<T>::f()
{std::cout << " template class impl" << std::endl;
}// 类模板声明与定义分开:类模板显示实例化
template class A < int > ;
template.cpp:

#include <iostream>
#include <string>
#include <stdexcept>
#include "template.hpp"void test_template1()
{int a = 3, b = 7;float x = 3.0, y = 7.0;//Calling template functionstd::cout << maximum<int>(a, b) << std::endl; //输出 7std::cout << maximum(a, b) << std::endl; //自动补充类型声明,输出 7std::cout << maximum<double>(x, y) << std::endl; //输出 7
}void test_template2()
{int i = 39;int j = 20;std::cout << "Max(i, j): " << Max(i, j) << std::endl;double f1 = 13.5;double f2 = 20.7;std::cout << "Max(f1, f2): " << Max(f1, f2) << std::endl;std::string s1 = "Hello";std::string s2 = "World";std::cout << "Max(s1, s2): " << Max(s1, s2) << std::endl;
}void test_template3()
{try {Stack<int>         intStack;  // stack of ints Stack<std::string> stringStack;    // stack of strings // manipulate int stack intStack.push(7);std::cout << intStack.top() << std::endl;// manipulate string stack stringStack.push("hello");std::cout << stringStack.top() << std::endl;stringStack.pop();//stringStack.pop();} catch (std::exception const& ex) {std::cerr << "Exception: " << ex.what() << std::endl;return;}
}void test_template4()
{pair <int> myints(100, 75);pair <float> myfloats(100.0, 75.0);std::cout << myints.module() << std::endl;std::cout << myfloats.module() << std::endl;
}void test_template5()
{PrintType<int> type_int;std::cout << type_int.type()<<std::endl;PrintType<float> type_float;std::cout << type_float.type() << std::endl;PrintType<std::string> type_string;std::cout << type_string.type() << std::endl;
}void test_template6()
{int ret = 0, a = 5, b = 7;ret = max_mum(a, b);std::cout << ret << std::endl;
}void test_template7()
{A<int> a;a.f();
}

主要参考文献:

1. https://zh.wikipedia.org/wiki/%E6%A8%A1%E6%9D%BF_(C%2B%2B)

2. http://blog.jobbole.com/83461/

3. https://docs.oracle.com/cd/E19205-01/820-1214/bkaew/index.html


GitHub:https://github.com/fengbingchun/Messy_Test

相关文章:

php面试问答

结合实际PHP面试&#xff0c;汇总自己遇到的问题&#xff0c;以及网上其他人遇到的问题&#xff0c;尝试提供简洁准确的答案包含MySQL、Redis、Web、安全、网络协议、PHP、服务器、业务设计、线上故障、个人简历、自我介绍、离职原因、职业规划、准备问题等部分 GitHub: https:…

图解LSTM与GRU单元的各个公式和区别

作者 | Che_Hongshu来源 | AI蜗牛车 &#xff08;ID: AI_For_Car)因为自己LSTM和GRU学的时间相隔很远&#xff0c;并且当时学的也有点小小的蒙圈&#xff0c;也因为最近一直在用lstm&#xff0c;gru等等&#xff0c;所以今天没事好好缕了一下&#xff0c;接下来跟着我一起区分并…

iphone越狱神器

前阵子刚刚换了iphone5&#xff0c;老婆的4就留给我了。一到手就决定越狱&#xff0c;无意中发现了一款越狱神器&#xff1a;爱思助手http://www.i4.cn/ 确实很好用转载于:https://blog.51cto.com/shanks/1306423

json11库的使用

JSON(JavaScript Object Notation)是一种轻量级的文本数据交换格式&#xff0c;易于让人阅读。同时也易于机器解析和生成。尽管JSON是Javascript的一个子集&#xff0c;但JSON是独立于语言的文本格式&#xff0c;并且采用了类似于C语言家族的一些习惯。JSON解析器和JSON库支持许…

覆盖10亿设备,月活2亿,快应用要取代App?

作者 | 伍杏玲 来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 2017 年 1 月 9 日&#xff0c;微信小程序横空出世&#xff0c;紧接着支付宝小程序、百度智能小程序、今日头条小程序、12 大厂商联盟的快应用等布局小程序。自此&#xff0c;小程序迅速改变国内移…

跨域的四种方式

本文主要是关于跨域的几种方式&#xff0c;关于什么是跨域这里就不多说了&#xff0c;写这个也是为了记住一些知识点的。 一. jsonp jsonp的跨域方式很容易理解&#xff0c;页面的的每一个script标签浏览器都会发送get请求获取对应的文本资源&#xff0c;获取到了之后&#xff…

使用模式创建一个面向服务的组件中间件

引言 在本文中&#xff0c;您将了解面向服务的组件中间件在用于资源有限的语音设备时&#xff0c;在设计阶段所应用的模式。它涵盖了项目的问题上下文&#xff0c;并被看成是一组决定因素&#xff0c;是对相关体系结构远景的一个简要概括。您还会得到一份描述&#xff0c;其中介…

OpenCV代码提取:遍历指定目录下指定文件的实现

OpenCV 3.1之前的版本&#xff0c;在contrib目录下有提供遍历文件的函数&#xff0c;用起来比较方便。但是在最新的OpenCV 3.1版本给去除掉了。为了以后使用方便&#xff0c;这里将OpenCV 2.4.9中相关的函数给提取了出来&#xff0c;适合在Windows 64bits上使用。directory.hpp…

姚班三兄弟3万块创业八年,旷视终冲刺港股

作者 | 余洋洋 杨健楷编辑 | 张丽娟来源 | CV智识&#xff08;ID:CVAI2019&#xff09;旷视此次 IPO 或将成为整个 AI 行业的信号&#xff0c;不只是“ 四小龙”的另外三家——商汤、依图、云从&#xff0c;整个 AI 行业的创业公司都将受到影响。8月25日晚&#xff0c;AI 独角兽…

Java类加载器详解

Java虚拟机中的类加载有三大步骤&#xff1a;&#xff0c;链接&#xff0c;初始化&#xff0e;其中加载是指查找字节流&#xff08;也就是由Java编译器生成的class文件&#xff09;并据此创建类的过程&#xff0c;这中间我们需要借助类加载器来查找字节流&#xff0e; Java虚拟…

linux svn客户端的使用

一下内容转载于&#xff1a;http://blog.chinaunix.net/space.php?uid22976768&doblog&id1640924。这个总结的很好~ windows下的TortoiseSVN是资源管理器的一个插件&#xff0c;以覆盖图标表示文件状态&#xff0c;几乎所以命令都有图形界面支持&#xff0c;比较好用&…

C++中vector的使用

向量std::vector是一种对象实体&#xff0c;能够容纳许多各种类型相同的元素&#xff0c;包括用户自定义的类&#xff0c;因此又被称为序列容器。与string相同&#xff0c;vector同属于STL(Standard Template Library)中的一种自定义的数据类型&#xff0c;可以广义上认为是数组…

说出来你可能不信,现在酒厂都在招算法工程师

导语&#xff1a;虽然夏日已过&#xff0c;但人们喝啤酒的热情还在持续高涨。不过随着大众的追求和理念提升&#xff0c;对于啤酒的要求也越来越高&#xff0c;比如逐渐兴起的精酿之风&#xff0c;都在印证人们在啤酒的口感和风味上&#xff0c;拥有更加「苛刻」的要求。那么这…

「前端面试题系列7」Javascript 中的事件机制(从原生到框架)

前言 这是前端面试题系列的第 7 篇&#xff0c;你可能错过了前面的篇章&#xff0c;可以在这里找到&#xff1a; 理解函数的柯里化ES6 中箭头函数的用法this 的原理以及用法伪类与伪元素的区别及实战如何实现一个圣杯布局&#xff1f;今日头条 面试题和思路解析最近&#xff0c…

安装Ecshop首页出现报错:Only variables should be passed by referen

出现下面这就话&#xff1a; Strict Standards: Only variables should be passed by reference in D:\wamp\ecshop\includes\cls_template.php on line 406 第406行&#xff1a;$tag_sel array_shift(explode( , $tag)); 解决办法 1 5.3以上版本的问题&#xff0c;应该也和配…

KDD 2019高维稀疏数据上的深度学习Workshop论文汇总

作者 | 深度传送门来源 | 深度传送门【导读】本文是“深度推荐系统”专栏的第九篇文章&#xff0c;这个系列将介绍在深度学习的强力驱动下&#xff0c;给推荐系统工业界所带来的最前沿的变化。本文简要总结一下阿里妈妈在 KDD 2019 上组织的第一届面向高维稀疏数据的深度学习实…

C++中fstream的使用

C中处理文件类似于处理标准输入和标准输出。类ifstream、ofstream和fstream分别从类 istream、ostream和iostream派生而来。作为派生的类&#xff0c;它们继承了插入和提取运算符&#xff08;以及其他成员函数&#xff09;&#xff0c;还有与文件一起使用的成员和构造函数。可将…

浅谈Disruptor

Disruptor是一个低延迟(low-latency)&#xff0c;高吞吐量(high-throughput)的事件发布订阅框架。通过Disruptor&#xff0c;可以在一个JVM中发布事件&#xff0c;和订阅事件。相对于Java中的阻塞队列(ArrayBlockingQueue,LinkedBlockingQueue)&#xff0c;Disruptor的优点是性…

web 服务发布注意事项

1、在发布的时候首先查看服务器对外开放的端口&#xff0c;如果没有最好和客户进行沟通需要开放那些对应的端口&#xff0c;要不外界无法访问发布的站点。 2、在oracle需要远程控制服务器的数据库的时候需要开发1521端口。转载于:https://www.cnblogs.com/jzm53550629/p/337563…

OpenCV代码提取:resize函数的实现

之前在http://blog.csdn.net/fengbingchun/article/details/17335477 中有过对cv::resize函数五种插值算法的介绍。这里将OpenCV3.1中五种插值算法的代码进行了提取调整。支持N通道uchar和float类型。经测试&#xff0c;与OpenCV3.1结果完全一致。实现代码resize.hpp&#xff1…

IBM重磅开源Power芯片指令集?国产芯迎来新机遇?

整理 | 郭芮出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;自去年 IBM 以 340 亿美元收购了 Linux 巨头红帽之后&#xff0c;这家 107 岁的蓝色巨人终于又在开源方面有大动作了&#xff01;近日在 Linux 基金会开源峰会上&#xff0c;IBM 宣布向开源社区提供 Powe…

构造函数不能为虚/重载函数总结

构造函数不能为虚/重载函数总结 作为一个类&#xff0c;他最基础的成员函数就要数构造函数了。这里我们先探讨一下构造函数为什么不能是虚函数。 在解决这个问题之前&#xff0c;要先明白类中函数的调用方式。一个类的函数共用一个函数空间&#xff0c;因此在实例化的对象中是不…

通过data:image/png;base64把图片直接写在src里

2019独角兽企业重金招聘Python工程师标准>>> 关于用base64存储图片 网页上有些图片的src或css背景图片的url后面跟了一大串字符&#xff0c;比如&#xff1a;data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAAkCAYAAABIdFAMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZS…

算力“竞速”,企业AI落地的当务之急

充足的算力资源&#xff0c;在数据量持续增长及算法持续复杂化的前提下&#xff0c;无疑是保障人工智能应用落地效果的关键。软件定义算力——打造AI转型最佳实践8月2日&#xff0c;第四范式联合英特尔共同举办了AI实践者之声夏令营活动。第四范式基础架构负责人刘一鸣以《软件…

内存检测工具Dr. Memory的使用

Dr. Memory是一个内存调试工具&#xff0c;它是一个开源免费的内存检测工具&#xff0c;它能够及时发现内存相关的编程错误&#xff0c;比如未初始化访问、内存非法访问、数组越界读/写、以及内存泄露等。它可以在Linux、Windows、Mac OS和Android操作系统上使用。关于Dr. Memo…

手把手教你如何新建scrapy爬虫框架的第一个项目(下)

前几天小编带大家学会了如何在Scrapy框架下创建属于自己的第一个爬虫项目&#xff08;上&#xff09;&#xff0c;今天我们进一步深入的了解Scrapy爬虫项目创建&#xff0c;这里以伯乐在线网站的所有文章页为例进行说明。在我们创建好Scrapy爬虫项目之后&#xff0c;会得到上图…

.net完整的图文验证

摘自:http://blog.csdn.net/durongjian/article/details/4336380 一、创建ValidaeCode类库工程&#xff1a; 1、创建ValidaeCode类库工程&#xff0c;在[解决胜方案资源管理器]面板中&#xff0c;右键单击[ValidateCode]节点&#xff0c;并选择[属性]命令。 2、单击[属性]命令&…

Tesseract-OCR 3.04在Windows7 vs2013上编译过程

从https://github.com/tesseract-ocr/tesseract下载最新源码,commit id: 86acff5, 2016.06.07. 里面有个vs2010目录&#xff0c;用vs2013打开tesseract.sln。Tesseract依赖图像库Leptonica&#xff0c;Leptonica的编译过程可以参考http://blog.csdn.net/fengbingchun/article/d…

【Laravel-海贼王系列】第九章, Events 功能解析

Events 注册 框架如何在启动的时候加载注册的事件?框架如何触发事件?1&#xff0c;先在容器中注册 events 的全局对象。 Application 构造函数中对 events 进行注册代码 protected function registerBaseServiceProviders(){$this->register(new EventServiceProvider($th…

触类旁通,经典面试题最长公共子序列应该这么答

作者 | labuladong来源 | labuladong&#xff08;ID:labuladong)【导读】最长公共子序列&#xff08;Longest Common Subsequence&#xff0c;简称 LCS&#xff09;是一道非常经典的面试题目&#xff0c;因为它的解法是典型的二维动态规划&#xff0c;大部分比较困难的字符串问…