C/C++从入门到弃坑

OpenCV

Windows 安装与配置

  • Installation in Windows

  • Build applications with OpenCV inside the “Microsoft Visual Studio”

  • 环境变量

C:\Program Files\opencv\build\x64\vc15\bin
  1. VC++目录–>包含目录
C:\Program Files\opencv\build\include
C:\Program Files\opencv\build\include\opencv		# 如果不用可以不添加
C:\Program Files\opencv\build\include\opencv2
  1. VC++目录–>库目录
C:\Program Files\opencv\build\x64\vc15\lib		# vc15对应vs2017
  1. 链接器–>输入–>附加依赖项
opencv_world343.lib			# release
opencv_world343d.lib		# debug

Linux 安装与配置

  • Installation in Linux
  1. Required packages
[compiler] sudo apt install build-essential
[required] sudo apt install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
[optional] sudo apt install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
  1. Getting OpenCV source code
git clone https://github.com/opencv/opencv.git
  1. Building OpenCV
cd opencv
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_GENERATE_PKGCONFIG=ON ..
make -j8
sudo make install
sudo vim /etc/ld.so.conf.d/opencv.conf
/usr/local/lib
sudo ldconfig
sudo vim /etc/bash.bashrc
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH
g++ test.cpp $(pkg-config --cflags --libs opencv4)

OpenCV函数

  • cv::imread()
  • “IMREAD_UNCHANGED”: 不改变图像格式打开
  • “IMREAD_GRAYSCALE”: 以灰度图像打开
  • “IMREAD_COLOR”: 以彩色图像打开

C/C++读写文件

open vs fopen

// C
FILE *f = fopen("file name", "xx");
fclose(f);
key word what mean
w
r
wb 二进制写
rb 二进制读
// C++
// 1
fstream f;
f.open("file name"; ios::xx);
// 2
fstream f("file name", ios::xx);

f.close();
key word what mean
in 读;文件不存在则创建(ifstream)
out 写;文件不存在则创建(ofstream)
ate 文件打开时,指针在文件最后;或改变指针位置,常和in、out联合使用
app 写;文件不存在则创建;若存在则在原文件内容后写入写的内容
trunc 在读写前先将文件长度截断为0
nocreate 文件不存在时产生错误,常和in或app联合使用
noreplace 文件存在时产生错误,常和out联合使用
binary 二进制格式文件
  • Difference
open fopen
缓冲文件系统(受内存缓冲区大小的影响)无缓冲 非缓冲文件系统(借助文件结构指针对文件进行管理)有缓冲
低级IO,系统指令,不可移植 高级IO,封装函数,可移植
一般打开设备文件 一般打开普通文件

关键字

bool BOOL

Keyword 类型 长度 取值
bool 布尔型 一个字节 false和true;0和1
BOOL int型 实际环境而定,一般可认为四个字节 FALSE和TRUE;0和非0

iostream

iostream:输入输出流。库的基础是istream和ostream类型。

#include

std::cout<< <> ;

extern

声明可以多次,定义只能一次

声明

  • 仅仅告诉编译器,有个某类型的变量会被使用,但编译器并不会为它分配任何内存
  • 一般在头文件中,对编译器说:我这里有一个函数叫f(),让编译器知道这个函数的存在
  • 不需要函数体

定义

  • 编译器会为它分配内存
  • 一般在源文件中,具体就是函数的实现过程,写明函数体
  • 需要函数体

函数的声明extern关键词可有可无,因为函数本身不加修饰的话就是extern。但在引用的时候一样是需要声明的。
全局变量在外部使用声明时,extern关键词是必须的,如果变量无extern修饰且没有显式的初始化,同样成为变量的定义

  • extern+变量
extern int a;				//声明一个全局变量a
int a;						//定义一个全局变量a
extern int a = 0;		//定义一个全局变量a,并给初值
int a = 0;					//定义一个全局变量a,并给初值
  • extern+函数
    定义时用extern,说明这个函数可以被外部引用
    声明时用extern,说明这是一个声明
    函数定义和声明时都可以将extern省略

extern “C”

const

类型修饰符,常类型/是指/使用/类型修饰符/修饰const说明的类型,常类型的变量或对象的值是不能被更新的(constant)。

作用

  • 定义const常量
const int Max = 100;
  • 便于进行类型检查
  • const常量有数据类型,编译器可以对const进行安全检查。
  • 宏常量没有数据类型,只进行字符替换,没有类型安全检查,并且在字符串替换时可能会产生意想不到的错误。
  • 改善程序健壮性(保护被修饰的东西)

防止意外的修改

void f(const int i){i = 10; //error!} //如果在函数体内修改i,编译器就会报错
  • 为函数重载提供了一个参考
class A{
	void f(int i) {...} 				//一个函数
	void f(int i) const {...}		//上一个函数的重载}
  • 提高效率

编译器不为不同const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得效率更高

  • 节省空间,避免不必要的内存分配

const定义常量从汇编角度来看,只能给出对应的内存地址,而不是像#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝

#define PI 3.14 //常量宏
const double pi = 3.14		//此时并未将Pi放入ROM中
double i = pi					//此时为pi分配内存,以后不再分配
double j = pi					//没有分配内存
double I = PI					//编译期间进行宏替换,分配内存
double j = PI					//再进行宏替换,又一次分配内存

使用

  • 定义变量
  • const修饰变量
TYPE const ValueName = value;
const TYPE valueName = value;

两种本质一样。const修饰的/类型为TYPE/变量value/是不可变的

  • 将const改为外部连接,作用扩大至全局,编译时会分配内存,并且可以不进行初始化,仅仅作为声明,编译器认为在程序其他地方进行定义。
extend const int ValueName = value;
  • 指针使用const
  • 指针本身是常量不可变
char * const pContent;
  • 指针所指向的内容是常量不可变
const char *pContent;
  • 两者都不变
const char* const pContent;
  • 区别

*cosnt,const修饰指针所指向的变量,指针指向为常量
const *,const修饰指针本身,指针本身为常量

  • 函数中使用const
  • 修饰函数参数
  • 传递过来的参数在函数内不可改变(无意义,因为Var本身就是形参)
void f(const int Var);
  • 参数指针所指内容为常量不可变
void f(const char* Var);
  • 参数指针本身为常量不可变(也无意义,因为char* Var也是形参)
void f(char* const Var);
  • 参数为引用,为了增加效率同时防止修改。
void f(const Class& Var); //引用参数在函数内不改变
void f(const TYPE& Var); //引用参数在函数内常量不可变

这样的const引用传递和最普通的函数按值传递的效果一模一样,禁止对引用的对象的一切修改,唯一不同的是按值传递会先建立一个对象的副本,然后传递过去,而它直接传递地址,所以const引用传递比按值传递更有效,另外只有引用const传递可以传递一个临时对象,以为临时对象都是const属性,且是不可见的,短时间存在一个局部域中,所以不能使用指针,只有引用的const传递能够捕捉到这个家伙。

  • 修饰函数返回值

使用不多,含义和const修饰普通变量以及指针的含义基本相同

const int f1()		//无意义,参数返回本身就是赋值
const int *f2()		//调用时const int *pValue = f2();可以把f2()看成一个变量,即指针内容不可变
int *const f3()		//调用时int *const pValue = f3();可以把f3()看成一个变量,即指针本身不可变

一般情况下,函数的返回值为某个对象时,如果将声明为const时,多用于操作符的重载
通常不建议使用const修饰函数的返回值类型/为某个对象或某个对象引用的情况。如果返回值为某个对象const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例),则返回值具有const属性,则返回实例只能访问类A中的共有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。

  • 类相关const
  • const修饰成员变量

const修饰类的成员函数,表示成员常量,不能被修改,同时只能在初始化列表中赋值

class A{
	const int nValue;				//成员常量不能被修改
	A(int x): nValue(x){...};		//只能在初始化列表中赋值
}
  • const修饰成员函数

const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。

class A{
	void f() const;		//常成员函数,不能改变对象的成员变量,也不能调用类中任何非const成员函数
}

对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的作用。

  • const成员函数不被允许修改它所在对象的任何一个数据成员;
  • const成员函数能够访问对象的const成员,而其它成员函数不可以。
  • const修饰类对象/对象指针/对象引用
  • const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。对于对象指针和对象引用也是一样。
  • const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。
class A{
	void f1();
	void f1() const;
}
const A aObj;
aObj.f1();			//错
aObj.f2()'			//正确
const A* aObj = new A();
aObj->f1();		//错
aObj->f2();		//正确

将const类型转化为非const类型的方法

const _ cast: const_cast (expression)
运算符用来修改类型的const或volatile属性。除了const或volatile修饰之外,type_id和expression的类型是一样的。

  • 常量指针被转化成非常量指针,并且仍然指向原来的对象;
  • 常量引用被转换成非常量引用,并且仍然指向原来的对象;
  • 常量对象被转换成非常量对象。

使用const的一些建议

  • 在弄清楚原委前提下,大量使用const,好处多多;
  • 避免一般的赋值操作错误,如将const变量赋值;
  • 在参数中使用const应使用引用或指针,而不是一般的对象实例;
  • const在成员函数的三种用法(参数、返回值、函数);
  • 不要轻易的将函数返回类型定位const;
  • 除了重载操作符外,一般不要将返回值类型定为对某个对象的const引用;
  • 任何不会修改数据成员的函数都应声明为const类型。

补充

  • 类内部的常量限制:使用这种类内部的初始化语法的时候,常量必须是被一个常量表达式的整型或枚举类型,而且是static和const形式。
  • 如何初始化内部的常量:
  • static和const并用,在外部初始化。
class A{
	public: A() {}
	private: static const int i: file: 
} //必须是静态的
const int A::i = 3;
  • 初始化列表
class A{
	public: A(int i = 0):test(i) {}
	private: const int i: 
}
  • 如果在非const成员函数,this指针只是一个类类型;如果在const成员函数中,this指针是一个const类类型的;如果在volatile成员函数中,this指针就是一个volatile类类型的
  • new返回的指针必须是const类型的

int a, int *a, int &a, (int) &a

  • int a
    定义一个整型类型变量a。
  • int *a
    定义一个指针类型a,a指向一个整型类型的变量,a中存放的是地址
  • int &a
int b = 1;
int &a = b;

a是b的引用,即a是b的别名。
&是引用声明符 地址
若改变a的值,b的值也会随着改变,因为a和b存储在同一存储单元,只是名字不一样而已。同一个地址。

  • 在声明引用变量类型时,必须同时使之初始化,即声明它是谁的引用,初始化后,不能再次成为其它变量的引用。
  • 引用不能为NULL
  • 数据类型
  • (int) &a

&a指a的地址,前面int是将*十六进制表示的*地址强制转换为int类型

构造函数

  • 作用
    构造函数是面向对象编程思想所需求的。
  • 创造对象。任何一个对象创建时,都需要初始化才能使用,所以任何类想要创建实例对象就必须具有构造函数。
  • 对象初始化。构造函数可以对对象进行初始化,并且是给与之格式(参数列表)相符合的对象初始化,是具有一定针对性的初始化函数

如果在类中我们不声明构造函数,JVM(Java Virtual Machine,Java虚拟机)会帮我们默认生成一个空参数的构造函数
如果在类中我们声明带参列表的构造函数,JVM就不会帮我们默认生成一个空参数的构造函数。
我们想要使用空参数的构造函数就必须自己去显式的声明一个空参的构造函数

public class student{ 
	private String name; 
	private String sex; 
	private int age; 
	public Student(){ 
	} 
	public Student(String name, String sex, int age){ 
		this.name = name; 
		this.sex = sex; 
		this.age = age;
	}
} 

实例

Student s = new Student(); 
s.setName("Ming"); 
s.setSex("femal"); 
s.setAge(20);

Student s = New Student("Ming", "femal", 20);

malloc calloc realloc

C语言内存分配方式

  • 从静态存储区域分配
    内存在程序编译的时候就已经分配好,这块内存在整个运行期间存在。例如全局变量、static变量。
  • 在栈上创建
    在执行函数时,函数内部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动释放。栈内存分配内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
  • 在栈上分配(动态内存分配)
    程序在运行的时候使用malloc或new申请任意大小的内存,程序员自己如何在何时使用free或delete释放内存。动态内存的生存期由用户决定,使用非常灵活。

C语言和内存申请相关的函数

  • malloc
void* malloc(unsigned size);

分配的内存位于堆中,并且没有初始化内存内容,因此基本上使用malloc之后调用函数memset初始化这部分内存空间。
在内存的动态存储区域中分配一块长度为size字节的连续区域,参数size为需要内存空间的长度,返回该区域的首地址。

  • calloc
void* calloc(size_t numElements, size_t sizeOfElement);

将初始化这部分内存设置为0。
与malloc相似,numElements为元素个数,参数sizeOfElement为申请地址单元的元素长度,即在内存中申请numElements*sizeOfElement字节大小的连续地址空间。

  • realloc
void* realloc(void* ptr, unsigned newsize);

对malloc申请的内存进行大小调整
给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度。

你可能感兴趣的:(C/C++从入门到弃坑)