github CPlusPlusThings 基础学习笔记

2023-11-09

来源:Light-City/CPlusPlusThings: C++那些事 (github.com)

const

const在*左边,被指物为常量,*右边指针为常量;尽量让函数返回一个常量值

int i = 0;
int *const p1 = &i;     //  不能改变 p1 的值,这是一个顶层
const int ci = 42;      //  不能改变 ci 的值,这是一个顶层
const int *p2 = &ci;    //  允许改变 p2 的值,这是一个底层
const int *const p3 = p2;   //  靠右的 const 是顶层 const,靠左的是底层 const
const int &r = ci;      //  所有的引用本身都是顶层 const,因为引用一旦初始化就不能再改为其他对象的引用,这里用于声明引用的 const 都是底层 const

当执行对象的拷贝操作时,常量是顶层const还是底层const的区别明显。其中,顶层 const 不受什么影响。

i = ci;     //  正确:拷贝 ci 的值给 i,ci 是一个顶层 const,对此操作无影响。
p2 = p3;    //  正确:p2 和 p3 指向的对象相同,p3 顶层 const 的部分不影响。

与此相对的,底层 const 的限制却不能被忽视。当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层 const 资格,或者两个对象的数据类型必须能够转换,一般来说,非常量可以转化为常量,反之不行。

int *p = p3;    //  错误:p3 包含底层 const 的定义,而p没有。假设成功,p 就可以改变 p3 指向的对象的值。
p2 = p3;            //  正确:p2 和 p3 都是底层 const
p2 = &i;            //  正确:int* 能够转化为 const int*,这也是形参是底层const的函数形参传递外部非 const 指针的基础。
int &r = ci;    //  错误:普通 int& 不能绑定到 int 常量中。
const int &r2 = i;  //  正确:const int& 可以绑定到一个普通 int 上。

只有常成员函数才有资格操作常量或常对象、调用常成员函数。对于类中的const成员变量必须通过初始化列表进行初始化,不能在类声明中初始化 const 数据成员。

class Apple{
private:
    int people[100];
public:
    Apple(int i); 
    const int apple_number;
};

Apple::Apple(int i):apple_number(i)
{
}

const对象只能访问const成员函数。

要使const变量能够在其他文件中访问,必须在文件中显式地指定它为extern。

//extern_file1.cpp
extern const int ext=12;
//extern_file2.cpp
#include<iostream>
extern const int ext;
int main(){
    std::cout<<ext<<std::endl;
}

static

变量:声明为static时,空间将在程序的生命周期内分配。多次调用函数,静态变量的空间也只分配一次,前一次调用中的变量值通过下一次函数调用传递,(例:count值累加)。

**类中的静态变量:**由对象共享,静态变量不能使用构造函数初始化。类中的静态变量应由用户使用类外的类名和范围解析运算符显式初始化。

class Apple 
{ 
public: 
	static int i; 
	Apple(){}; 
}; 

int Apple::i = 1; 

int main() 
{ 
	Apple obj; 
	cout << obj.i; //1
} 

**对象:**在声明为static时具有范围,直到程序的生命周期。

**类中的静态函数:**建议使用类名和范围解析运算符调用静态成员。允许静态成员函数仅访问静态数据成员或其他静态成员函数,它们无法访问类的非静态数据成员或成员函数。

this

this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数.

在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this。

当参数与成员变量名相同时,如this->n = n (不能写成n = n)。

inline

内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。

inline是一种“用于实现的关键字,而不是用于声明的关键字”。

类中定义的函数是隐式内联函数。声明要想成为内联函数,必须在实现处(定义处)加inline关键字。inline virtual 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who())。

sizeof

  • 空类大小为1字节。

  • 类的static成员变量不影响类的大小,被编译器放在程序的一个global data members中。不管这个类产生了多少个实例,还是派生了多少新的类,静态数据成员只有一个实例。静态数据成员,一旦被声明,就已经存在。

  • 对于包含虚函数的类,不管有多少个虚函数,只有一个虚指针,vptr的大小,即8。

  • 普通单继承,继承就是基类+派生类自身的大小(注意字节对齐),类的数据成员按其声明顺序加入内存,与访问权限无关,只看声明顺序。派生类继承基类vptr,8字节。

  • 派生类虚继承多个虚函数,会继承所有虚函数的vptr。

class A {
public:
	char b;
	static int c;
	virtual void fun();
};
void A::fun(){}

class A1 {
public:
	char a;
	int b;
};

class B1 :A1
{
public:
	short a;
	long b;
};

class C1 {
public:
	A1 a;
	int b;
};

class A2 {
	void virtual fun();
};
class B2 {
	void virtual fun2();
};
class C2 :virtual public A2, virtual public B2
{
	void virtual fun3();
};

int A::c = 2;

int main() {
	A a;
	cout << sizeof(A) << endl;//16
	cout << A::c << endl;
	cout << sizeof(A1) << endl;//8
	cout << sizeof(B1) << endl;//16
	cout << sizeof(C1) << endl;//12
	cout << sizeof(A2) <<" " << sizeof(B2)<<" " << sizeof(C2)<< endl;//8 8 32
	return 0;
}

函数指针

typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型
// 回调函数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
// 获取随机值
int getNextRandomValue(void)
{
    return rand();
}
int main(void)
{
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

纯虚函数和抽象类

  • 纯虚函数:没有函数体,声明赋值0(定义为虚函数是为了允许用基类的指针来调用子类的这个函数。定义为纯虚函数才代表函数没有被实现。)

  • 抽象类:包含纯虚函数的类;只能作为基类派生新类,由派生类继承实现,如果派生类不覆盖纯虚函数也会变成抽象类,不能创建对象;成员函数可以调用纯虚函数,但构造函数/析构函数不能使用纯虚函数。

构造函数不能是虚函数,而析构函数可以是虚析构函数。

class Base {
	int x;
public:
	virtual void show() = 0;
	int gexX() {
		return 0;
	}
	Base() { cout << "Constructor: Base" << endl; }
	virtual ~Base() { cout << "Destructor : Base" << endl; }
};

class Derived :public Base {
public:
	void show() {
		cout << "in derived" << endl;
	}
	Derived() { cout << "Constructor: Derived" << endl; }
	~Derived() { cout << "Destructor : Derived" << endl; }
};

int main() {
	//Base b; //error: An abstract class cannot be instantiated
	Base *bp = new Derived();//基类指针指向派生类对象
	bp->show();
	delete bp;

	return 0;
}

vptr,vtable

C++的动态多态性是通过虚函数来实现的。简单的说,通过virtual函数,指向子类的基类指针可以调用子类的函数。每个使用虚函数的类(或者从使用虚函数的类派生)都有自己的虚拟表。该表只是编译器在编译时设置的静态数组。虚拟表中的每个条目只是一个函数指针,指向该类可访问的派生函数。编译器还会添加一个隐藏指向基类的指针,我们称之为vptr。vptr在创建类实例时自动设置,以便指向该类的虚拟表。

Base *pt = new Derived(); // 基类指针指向派生类实例
cout<<"基类指针指向派生类实例并调用虚函数"<<endl;
pt->fun1();

其过程为:首先程序识别出fun1()是个虚函数,其次程序使用pt->vptr来获取Derived的虚拟表。第三,它查找Derived虚拟表中调用哪个版本的fun1()。这里就可以发现调用的是Derived::fun1()。因此pt->fun1()被解析为Derived::fun1()!

virtual

  • 虚函数的调用取决于指向或者引用的对象的类型,而不是指针或者引用自身的类型。基类指针指向继承类对象,则调用继承类对象的函数。

  • 默认参数是静态绑定的,虚函数是动态绑定的。 默认参数的使用需要看指针或者引用本身的类型,而不是对象的类型。

  • 静态函数不可以声明为虚函数,同时也不能被const 和 volatile关键字修饰。static成员函数不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义。虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成,并且只能用this指针来访问它,静态成员函数没有this指针,所以无法访问vptr。

  • **构造函数不可以声明为虚函数。同时除了inline|explicit之外,构造函数不允许使用其它任何关键字。**尽管虚函数表vtable是在编译阶段就已经建立的,但指向虚函数表的指针vptr是在运行阶段实例化对象时才产生的。 如果类含有虚函数,编译器会在构造函数中添加代码来创建vptr。如果构造函数是虚的,那么它需要vptr来访问vtable。

  • 析构函数可以声明为虚函数。如果我们需要删除一个指向派生类的基类指针时,应该把基类析构函数声明为虚函数。

  • 虚函数为私有函数时,int main()必须声明为基类的友元,否则编译失败。

  • 虚函数可以是内联函数,内联(编译器)是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联。

volatile

  • 将变量i加上volatile修饰,则编译器保证对变量i的读写操作都不会被优化,从而保证了变量i被外部程序更改后能及时在原程序中得到感知。

  • 当多个线程共享某一个变量时,变量采用 volatile 声明,防止编译器优化把变量从内存装入CPU寄存器中,当一个线程更改变量后,未及时同步到其它线程中导致程序出错。

  • volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素(操作系统、硬件、其它线程等)更改。所以使用 volatile 告诉编译器不应对这样的对象进行优化。

  • volatile 关键字声明的变量,每次访问时都必须从内存中取出值(没有被 volatile 修饰的变量,可能由于编译器的优化,从 CPU 寄存器中取值)

  • const 可以是 volatile (如只读的状态寄存器)

  • 指针可以是 volatile

assert

断言,是宏,而不是函数,检查逻辑上不可能的情况。如果它的条件返回错误,则终止程序执行。在引用<assert.h>头文件之前#define NDEBUG禁用断言。

#include <stdio.h> 
#include <assert.h> 

int main() 
{ 
    int x = 7; 
    /*  Some big code in between and let's say x  
    is accidentally changed to 9  */
    x = 9; 
    // Programmer assumes x to be 7 in rest of the code 
    assert(x==7); 
    /* Rest of the code */
    return 0; 
} 

输出:

assert: assert.c:13: main: Assertion 'x==7' failed.

bit field

数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作,不可移植。

//struct bit_field_name
//{
//	type member_name : width;
//};

struct stuff 
{
    unsigned int field1: 30;
    unsigned int       : 2;//填充作用
    unsigned int field2: 4;
    unsigned int       : 0;
    unsigned int field3: 3; 
};//该结构现在大小为 3 * 32 = 96 Bits

一个位域成员不允许跨越两个 unsigned int 的边界,编辑器会自动移位位域成员使其按照 unsigned int 的边界对齐。也可以使用一个宽度为 0 的未命名位域成员令下一位域成员与下一个整数对齐。

extern C

用于C++链接在C语言模块中定义的函数

  • C++调用C函数:
//xx.h
extern int add(...)

//xx.c
int add(){
}

//xx.cpp
extern "C" {
    #include "xx.h"
}
  • C调用C++函数
//xx.h
extern "C"{
    int add();
}
//xx.cpp
int add(){
}
//xx.c
extern int add();

不过与C++调用C接口不同,C++确实是能够调用编译好的C函数,而这里C调用C++,不过是把C++代码当成C代码编译后调用而已。也就是说,C并不能直接调用C++库函数。

struct

struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。

区别:

默认的继承访问权限。struct 是 public 的,class 是 private 的。

struct 作为数据结构的实现体,它默认的数据访问控制是 public 的,而 class 作为对象的实现体,它默认的成员变量访问控制是 private 的。

union

union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点:

  • 默认访问控制符为 public
  • 可以含有构造函数、析构函数
  • 不能含有引用类型的成员
  • 不能继承自其他类,不能作为基类
  • 不能含有虚函数
  • 匿名 union 在定义所在作用域可直接访问 union 成员
  • 匿名 union 不能包含 protected 成员或 private 成员
union UnionTest {
	UnionTest() :i(10) { print(i); }
	~UnionTest() {};
	int i;
	int j;
private:
	void print(int i) { cout << i << endl; }
};

static union {//全局匿名联合必须是静态的
	int i;
	double d;
};

int main() {
	::i = 20;
	std::cout << ::i << std::endl;  // 输出全局静态匿名联合的 20
	UnionTest t;
	t.i = 5;
	printf("now t.i is %ld! the address is %p\n", t.i, &t.i);//5 addr1
	t.i = 6;
	printf("now t.j is %ld! the address is %p\n", t.j, &t.j);//6 addr1
	printf("now t.i is %ld! the address is %p\n", t.i, &t.i);//6 addr1
	return 0;
}

explicit

  • explicit 修饰构造函数时,可以防止隐式转换和复制初始化
  • explicit 修饰转换函数时,可以防止隐式转换,但按语境转换除外
class Test1
{
public :
	Test1(int num):n(num){}
private:
	int n;
};
class Test2
{
public :
	explicit Test2(int num):n(num){}
private:
	int n;
};
 
int main()
{
	Test1 t1 = 12;
	Test2 t2(13);
	Test2 t3 = 14;//error
	return 0;
}

friend

在类声明的任何区域中声明,而定义则在类的外部。友元函数只是一个普通函数,并不是该类的类成员函数,友元函数中通过对象名来访问该类的私有或保护成员。

友元类的声明在该类的声明中,而实现在该类外。类B是类A的友元,那么类B可以直接访问A的私有成员。

  • 友元关系没有继承性
    假如类B是类A的友元,类C继承于类A,那么友元类B是没办法直接访问类C的私有或保护成员。
  • 友元关系没有传递性
    假如类B是类A的友元,类C是类B的友元,那么友元类C是没办法直接访问类A的私有或保护成员,也就是不存在“友元的友元”这种关系。
class A {
public:
	A(int _a) :a(_a) {};
	friend int getA(A&aa);
	friend class B;
private:
	int a;
};
class B {
public:
	int getA(A ca) {
		return ca.a;
	}
};

int getA(A &aa) {
	return aa.a;
}

int main() {
	A a(3);
	cout << getA(a) << endl;//3
	B b;
	cout << b.getA(a) << endl;//3
	return 0;
}

using

namespace ns1 {
    void func(){cout<<"ns1::func"<<endl; }
}
namespace ns2 {
    using ns1::func;    /// ns1中的函数
}
  • 改变访问性:在派生类的内部通过using声明语句 , 我们可以忽略继承方式 ,改变派生类中可访问的基类成员在派生类中的访问权限 。

  • **函数重载:**在继承过程中,派生类可以覆盖重载函数的0个或多个实例,一旦定义了一个重载版本,那么其他的重载版本都会变为不可见。在派生类中使用using声明语句指定一个名字而不指定形参列表,可以把该函数的所有重载实例添加到派生类的作用域中。

  • 对应typedef A B,使用using B=A可以进行同样的操作。

typedef vector<int> V1; 
using V2 = vector<int>;

::

  • 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间
  • 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的
  • 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的
int count=0;    // 全局(::)的count
class A {
public:
    static int count;  // 类A的count (A::count)
};
// 静态变量必须在此处定义
int A::count;
int main() {
    ::count=1; // 设置全局的count为1
    A::count=5; // 设置类A的count为2
    cout<<A::count<<endl;
//    int count=3; // 局部count
//    count=4;     // 设置局部的count为4
    return 0;
}

enum

C++11 标准中引入了“枚举类”(enum class)。

  • 新的enum的作用域不在是全局的

  • 不能隐式转换成其他类型

  • 可以指定用特定的类型来存储enum

enum class Color3:char;  // 前向声明

// 定义
enum class Color3:char 
{
    RED='r',
    BLUE //‘s'
};
char c3 = static_cast<char>(Color3::RED);

类中的枚举常量,某些常量只在类中有效:

class Person{
public:
    typedef enum {
        BOY = 0,
        GIRL
    }SexType;
};
//访问的时候通过,Person::BOY或者Person::GIRL来进行访问。

枚举常量不会占用对象的存储空间,它们在编译时被全部求值。

枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点。

decltype

decltype“查询”表达式的类型,并不会对表达式进行“求值”,语法是:

decltype (expression)
  • 推导表达式类型
int i = 4;
decltype(i) a; //推导结果为int。a的类型为int
  • 定义类型
using ptrdiff_t = decltype((int*)0 - (int*)0);
using nullptr_t = decltype(nullptr);
vector<int >vec;
typedef decltype(vec.begin()) vectype;
for (vectype i = vec.begin; i != vec.end(); i++)...
  • 重用匿名类型
struct 
{
    int d ;
    double b;
}anon_s;
decltype(anon_s) as ;//定义了一个上面匿名的结构体
  • 泛型编程中结合auto,用于追踪函数的返回值类型
template <typename T>
auto multiply(T x, T y)->decltype(x*y)
{
	return x*y;
}

类型推导规则:

  • 如果 exp 是一个不被括号( )包围的表达式,或者是一个类成员访问表达式,或者是一个单独的变量,那么 decltype(exp) 的类型就和 exp 一致,这是最普遍最常见的情况。

  • 如果 exp 是函数调用,那么 decltype(exp) 的类型就和函数返回值的类型一致。

  • 如果 exp 是一个左值,或者被括号( )包围,那么 decltype(exp) 的类型就是 exp 的引用;假设 exp 的类型为 T,那么 decltype(exp) 的类型就是 T&。

**左值和右值:**左值是指那些在表达式执行结束后依然存在的数据,也就是持久性的数据;右值是指那些在表达式执行结束后不再存在的数据,也就是临时性的数据。对表达式取地址,如果编译器不报错就为左值,否则为右值。

引用与指针

定义引用的时候必须为其指定一个初始值,但是指针却不需要。引用不能更换目标,指针可以随时改变指向。

int &r;    //不合法,没有初始化引用
int *p;    //合法,但p为野指针,使用需要小心

使用const reference参数作为只读形参,既可以避免参数拷贝还可以获得与传值参数一样的调用方式。

void test(const vector<int> &data)
{...}

底层实现时C++编译器实现这两种操作的方法完全相同。

预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。

#define <宏名> <字符串>
#define PI 3.1415926
#define <宏名> (<参数表>) <宏体>
#define A(x) x

do{…}while(0)的使用

#define fun() f1();f2();
if(a>0)
	fun()

这个宏被展开后就是:

if(a>0)
	f1();
	f2();

本意是a>0执行f1 f2,而实际是f2每次都会执行,所以就错误了。

为了解决这种问题,在写代码的时候,通常可以采用{}块。

#define fun() {f1();f2();}
if(a>0)
	fun();

但是会发现上述宏展开后多了一个分号,实际语法不太对。使用do-while的用法,让接口容易被正确使用,而不易被误用。

#define DOSOMETHING() \
        do{ \
          foo1();\
          foo2();\
        }while(0)\
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

github CPlusPlusThings 基础学习笔记 的相关文章

随机推荐

  • 驱动的调用

    目录 设备文件 编辑 测试驱动 读写回环测试 步骤 源文件 详细的讲解看注释即可 应用和驱动之间的数据交换 在应用层调用open来打开这个系统文件 在向这个设备文件使用read write等即可调用驱动的函数去工作 设备文件 设备文件连接着
  • Sparkstreaming读取kafka数据写入hive和es

    一 主要流程 此demo用到的软件如下 软件需先自行安装 springboot 1 5 9 RELEASE hadoop 2 7 2 spark 2 1 1 elasticsearch 5 2 2 kafka 0 10 2 1 hive s
  • Cron表达式解读

    背景说明 解读0 0 10 与 0 10 的区别 各个字符代表的含义 0代表从0分开始 代表任意字符 代表递增 1 0 0 10 代表从0分钟开始 每10分钟执行任务一次 启动时间 xx 20 05 第一次执行时间 xx 20 10 第二次
  • 项目心得(三)

    赛车游戏项目心得 介绍 确定项目 分工 进度规划 资源结构 游戏数据结构 遇到的问题 项目展示 开始场景 主菜单场景 成就查询场景 诗词系统场景 无尽塔场景 车库场景 阶位场景 视频演示 项目文件 总结 介绍 我带领的第二次小组团队项目 大
  • 1.1 密码学哈希函数

    我们需要理解的第一个密码学的基础知识是密码学哈希函数 哈希函数是一个数学函数 具有以下三个特性 其输入可为任意大小的字符串 它产生固定大小的输出 为使本章讨论更具体 我们假设输出值大小为256位 但是 我们的讨论适用于任意规模的输出 只要其
  • 操作系统虚拟机linux系统内建立的文件为只读,如何可读可写?

    1 先建立文件 按照自己的需求建立文件 2 打开主目录 发现a c文件为只读形式 3 在终端输入chmod 666 a c 4 返回主目录 文件为可读可写形式 5 打开a c文件就可以编辑代码并保存啦
  • llS6 and llS7解析漏洞

    1 什么是llS Internet Information Services 互联网信息服务 是微软公司由微软公司提供的基于运行Microsoft windows的互联网基本服务 web服务 因为IIS是在windows操作系统平台下开发的
  • 2021-10-25尤破金10.25黄金今日行情价格走势分析及黄金原油最新策略解套

    黄金行情走势分析 周一 10月25日 国际金价徘徊在1800美元重要心理关口附近 美元指数反弹限制了金价升势 在美联储主席鲍威尔表示通胀可能持续到明年后 投资人思索美联储可能会如何应对通胀压力 在鲍威尔上周五 10月22日 表示美联储应开始
  • Pytorch分布式训练(一)

    参考文献 Writing Distributed Applications with PyTorch PyTorch Tutorials 2 0 1 cu117 documentation 33 完整讲解PyTorch多GPU分布式训练代码
  • 简单报价单模板_科普:小程序定制和模板开发有什么区别?

    小程序常见的开发方式有三种 自己源代码开发 找外包团队定制开发 使用小程序模板类开发工具 对于不懂技术的小白来说 源代码开发困难太大 那么后两种方式该如何选择呢 它们到底都有什么区别 接下来就跟大家科普一下这些知识 1 成本不同 小程序模板
  • ClickHouse(四)表引擎

    官网 表引擎 ClickHouse文档 表引擎在 ClickHouse 中的作用十分关键 直接决定了数据如何存储和读取 是否支持并发读写 是否支持 index 支持的 query 种类 是否支持主备复制等 1 表引擎概述 ClickHous
  • unity3D之动态的创建球体游戏对象js

    function OnGUI if GUILayout Button 创建立方体 GUILayout Height 50 var objCube GameObject CreatePrimitive PrimitiveType Sphere
  • JS 插入排序

    算法描述 插入排序的算法描述是一种简单直观的排序算法 它的工作原理是通过构建有序序列 对于未排序数据 在已排序序列中从后向前扫描 找到相应位置并插入 一般来说 插入排序都采用in place在数组上实现 具体算法描述如下 从第一个元素开始
  • 【OpenCV4】拉普拉斯算子提取边缘 cv::Laplacian() 用法详解和代码示例(c++)

    作用原理 拉普拉斯算子可以用于边缘检测 同时该算子不具有方向性 可以同时检测到 X 方向和 Y 方向的边缘 综合后检测出图像的边缘 即拉普拉斯算子是 各向同性 的 这在很多情况下是一个优点 因为我们一般来说会同时关注 X 方向和 Y 方向的
  • xcode4的环境变量,Build Settings参数,workspace及联编设置

    一 xcode4中的环境变量 BUILT PRODUCTS DIR build成功后的 最终产品路径 可以在Build Settings参数的Per configuration Build Products Path项里设置 TARGET
  • 英语台词--冰与火之歌

    Your roof your rules 你的地盘 你做主
  • C++基础——常引用与类型转换详解

    通过前两篇对引用的讲解 想必大家都对引用有了较为深刻的理解 没看过的小伙伴可以去看看 C 基础 引用讲解1 C 基础 引用讲解2 目录 一 常引用 1 权限的平移 2 权限的放大 3 权限的缩小 二 引用的类型转换 一 常引用 这次我来说一
  • 史上最全的Python兼职接单挣钱教程,十分详细(附基础教程)

    学python编程能挣钱吗 怎么挣钱 答案是可以的 有两点我都赚到钱的方法 接私活和自媒体 一 赚钱第一种方式 接私活 刚学会python那会 就有认识的朋友介绍做一个网站的私活 当时接单赚了4K 仅代表本人个人收益 后又自己接过开发网站后
  • A2W和W2A 很好的多字节和宽字节字符串的转换宏

    分享一下我老师大神的人工智能教程 零基础 通俗易懂 http blog csdn net jiangjunshow 也欢迎大家转载本篇文章 分享知识 造福人民 实现我们中华民族伟大复兴 作者 朱金灿 来源 http blog csdn ne
  • github CPlusPlusThings 基础学习笔记

    来源 Light City CPlusPlusThings C 那些事 github com 目录 const static this inline sizeof 函数指针 纯虚函数和抽象类 vptr vtable virtual vola