c++基础学习记录

文章目录

      • vector
      • 构造函数后面的冒号
      • c++中inline使用
      • ->符号
      • C++中基本类型的数组使用的时候需要初始化,不然数组中的值不确定
      • c++ auto关键字
      • std::make_shared使用
      • c++中基本类型的字节数
      • 代码中&的使用
      • extern关键字
      • c++中的friend用法
      • c++中使用new和不使用new创建类对象的区别
      • typedef 声明类型
      • template使用
      • c++中function使用
      • c++中lambda表达式中的=和&的区别
      • using
      • static 变量
      • unique_ptr
      • c 和 c++ 中动态分配内存的方式差异
      • 左右值
      • 不完整类型

vector

返回一个空的vector

// C11以前
return vector<string>();
// c11起
return {};

构造函数后面的冒号


class A
{
public:
    A(int val)
    {
        x = val;
        cout << " A is " << val << endl;
    }
    int x = 0;
};

class B : A
{
public:
    B(int b) : A(b)
    {
        cout << " " << b << endl;
    }
};

B类的构造函数后面的冒号表示掉用父类的构造函数

c++中inline使用

c++中如果有一些函数被频繁掉用,可以使用inline关键字定义一个方法,这样这个方法就变成了内敛函数,使用内联函数的地方会在运行的时候被替换为内联函数的方法体,通过这种方式减少函数栈的调用。

使用限制:

  • inline只适合涵数体内代码简单的函数数使用,不能包含复杂的结构控制语句例如while、switch,并且内联函数本身不能是直接递归函数(自己内部还调用自己的函数);
  • 使用内联函数会增大代码体积,消耗更多的内存
inline float cube(const float a) { return a * a * a; }

->符号

c++中 ->用于指针上用来提取成员变量

    ListNode *dummyHead = new ListNode(0);
    cout << (*dummyHead).val << endl;
    cout << dummyHead->val << endl;

C++中基本类型的数组使用的时候需要初始化,不然数组中的值不确定

    int a[100];
    for (int i = 0; i < 10; i++)
    {
        cout << " i is " << a[i] << endl;
    }

上面的代码运行结果如下,值会是个非法值。(之前一直在写java习惯了不初始化使用默认值,结果写c++基本代码都不会写)

i is 1107296256
i is 0
i is 131431020
i is 1
i is 131889808
i is 1
i is -281910792
i is 32766
i is 9277440
i is 1

c++ auto关键字

c++11开始后的auto关键字的使用:

  • 声明变量时根据初始化表达式自动推断该变量的类型
  • 声明函数时函数返回值的占位符

比如遍历一个容器的时候,可以使用auto快速遍历:

 std::vector<int> vect; 
 for(auto it = vect.begin(); it != vect.end(); ++it)
 {  //it的类型是std::vector::iterator
  }
  // 或者

std::make_shared使用

查看c++官网参考

Allocates and constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr that owns and stores a pointer to it (with a use count of 1).

make_shared 智能指针的一种,智能指针是用来管理指针的类,用来存储指向动态分配对象的指针。自动释放动态分配的对象。

  std::shared_ptr<int> foo = std::make_shared<int>(10);
    // same as:
    std::shared_ptr<int> foo2(new int(11));

    auto bar = std::make_shared<int>(20);

    std::cout << "*foo: " << *foo << '\n';
    std::cout << "*foo2: " << *foo2 << '\n';
    std::cout << "*bar: " << *bar << '\n';
    return 0;
    

make_shared 官方参考

c++中基本类型的字节数

float 内存中占4个字节,有效数位是7位
double 占8个字节,有效数位是16位

代码中&的使用

变量的前面加&表示取变量地址(赋值给指针), 如:int a = 0; int *pa = &a; a和pa是变量;*pa是指针;&a是取变量a的地址。

类型后面表示引用,引用即变量的别名。
例如:

int a = 0; int &ref = a;  

例如我们在函数参数列表中定义形参为引用传递的方式:

void Fun(int &a){ // 这里的a就是一个传入的参数的别名
}

extern关键字

c++中变量分为声明和定义两个阶段:

  • 当使用extern 声明一个全局变量的时候比如:extern int j; 表示该变量定义于其它单元。
  • 当使用extern定义一个变量的时候,如:extern const int J = 10; 会让该变量拥有外部链接,否则该变量只有内部链接。
  • 当使用extern “C” 修饰代码块或者声明的时候例如,每一个jni方法前面的extern “c” 表明后面的代码块使用c语言的编译方式。

例子:
我们要在A.cpp/h 中定一个全局变量,然后再B.cpp/h中使用
在A.cpp中定义一个全局变量

int testGLobalVal=100;

然后在B.cpp文件中使用extern进行声明:

extern int testGLobalVal;

然后在B.cpp中我们就可以使用该变量
参考:
https://www.runoob.com/w3cnote/cpp-static-usage.html

c++中的friend用法

友元类:定义一个类时,主动声明哪些类或者函数是他的朋友,可以对friend类提供对他们自身的private和protected变量的访问特权

  • 将类声明为自己的有元,这样这个类就可以访问自己的私有或者private变量

A.hpp

#ifndef __A
#define __A
#include 
#include 

using namespace std;

class A
{
    friend class B;

public:
    ~A();
    static void func()
    {
        cout << " this is in A " << endl;
    }

private:
    A(){};
    static const A Test;
};

#endif

A中定义一个private的变量,将B声明为自己的友元,这样B中就可以访问A中的私有变量
B.hpp

#ifndef __B
#define __B

class B
{
public:
	B();
	void func();
};

#endif

友元类中定义的函数使用到了原始类的私有变量,那么就需要在友元类定义的文件中包含原始类定义的头文件,所以这里导入了A.hpp,
原始类的定义中(包含友元类声明的那个类A.hpp),就不需要包含友元类的头文件,也不需要在类定义前去声明友元类,因为友元类的声明自身就是一种声明(它指明可以在类外找到友元类)
B.cpp

#include 
#include 
#include "B.hpp"
#include "A.hpp"
using namespace std;

B::B()
{
    cout << " construct a b val " << endl;
}

void B::func()
{
    cout << " enter b " << endl;
    A::Test.func();
}

int main()
{
    B bb;
    bb.func();
    return 0;
}
输出:
 construct a b val 
 enter b 
 this is in A
  • 友元函数,表示这个函数可以访问到当前类的private和protected成员
    修改上面的代码:
    修改A.hpp中的代码:
    // A中声明B中的func1为友元函数
    friend void B::func1();

修改B.hpp中的代码:

#ifndef __B
#define __B

class B
{
public:
	B();
	void func1();
	void func2();
};

#endif

B.cpp

#include 
#include 
#include "B.hpp"
#include "A.hpp"
using namespace std;

B::B()
{
    cout << " construct a b val " << endl;
}

void B::func1()
{
    cout << " enter func1 " << endl;
    A::Test.func();
}

void B::func2()
{
    cout << " enter func2 " << endl;
    // 这个函数调用的话会报错,因为只声明了func1为友元函数
    // A::Test.func();
}

int main()
{
    B bb;
    bb.func1();
    bb.func2();
    return 0;
}

参考:https://blog.csdn.net/bandaoyu/article/details/111591588

c++中使用new和不使用new创建类对象的区别

  • c++中使用new创建对象,使用完后需要使用delete删除,可以一处创建然后在多处调用
CTest*  pTest = new  CTest();
delete pTest;

使用new创建的对象使用一个指针来接收

  • new创建对象使用的是堆空间,不用new定义类对象的方式使用的是栈空间,栈空间当当前函数结束的时候,栈用的内存会被系统自动释放。

typedef 声明类型

c++中我们可以使用typedef来声明一个新的类型名,用新的类型名称来代替我们的类型:

typedef int Integer; // 使用Integer标识符来代表int类型
typedef struct
{
 	int age;
    int height;
    int weight;
} HUMAN;  // 这里使用HUMAN是新的类型的名称,而不是机构体的变量名
 
    HUMAN per1;
    per1.age = 10;

template使用

模版是泛型编程的基础,使用模版我们可以实现泛型编写函数或者类:
泛型函数:

template <typename T>
inline T const& Max (T const& a, T const& b) 
{ 
    return a < b ? b:a; 
} 
// 上面定义了一个比较大小的函数模版,这样我们在使用的时候可以传入不同的类型
    double f1 = 13.5; 
    double f2 = 20.7; 
    cout << "Max(f1, f2): " << Max(f1, f2) << endl; 
 
    string s1 = "Hello"; 
    string s2 = "World"; 
    cout << "Max(s1, s2): " << Max(s1, s2) << endl; 

类模版

template <class T>
class Stack { 
  private: 
    vector<T> elems;     // 元素 
 
  public: 
    void push(T const&);  // 入栈
    void pop();               // 出栈
    T top() const;            // 返回栈顶元素
    bool empty() const{       // 如果为空则返回真。
        return elems.empty(); 
    } 
}; 
// 在定义template中的方法的时候使用下面的方式:
template <class T>
void Stack<T>::push(T const &elem)
{
    // 追加传入元素的副本
    elems.push_back(elem);
}
... 

参考:
https://www.runoob.com/cplusplus/cpp-templates.html

c++中function使用

使用function定义一个函数

 // [&]表示以引用方式捕获块外的所有变量
 function<int(int, int)> dfs = [&](int start, int end)
 {
	
 };

more:https://www.cnblogs.com/ChinaHook/p/7658411.html

c++中lambda表达式中的=和&的区别

c++lambda在捕获外部参数的列表中[=]表示是值传递,会使用对应的拷贝构造函数,[&]表示以引用方式处理外部变量。

using

  1. 使用命名空间:
// 在代码中定义命名空间
namespace xxxxx;

// 使用我们定义的命名空间
using namespace xxxxx;
  1. 在子类中使用基类成员
class T5Base
{
public:
    T5Base() : value(55) {}
    virtual ~T5Base() {}
    void test1() { cout << "T5Base test1..." << endl; }

protected:
    int value;
};

class T5Derived : private T5Base
{
public:
    using T5Base::test1;
    using T5Base::value;
    void test2() { cout << "value is " << value << endl; }
};

使用using,我们可以访问private化的基类成员,因为using可以将在别处定义的名称 引入到using声明出现的区域:

Introduces a name that is defined elsewhere into the declarative region where this using-declaration appears.
参考链接:
https://www.runoob.com/cplusplus/cpp-inheritance.html

  1. 别名指定
using value_type = _Ty

以后使用value_type value; 就代表_Ty value;

static 变量

  1. 在修饰局部变量的时候,static 修饰的静态局部变量只执行初始化一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
  2. static修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。
  3. static 修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。

unique_ptr

unique_ptr是一个独占型的智能指针,他不允许其他指针共享其内部的指针,不能通过赋值将一个unique_ptr赋值给另一个另一个。但可以通过函数返回给其他的unique_ptr,还可以通过std::move来转移到其他的unique_ptr,这样它本身就不再拥有原来指针的所有权了。

unique_ptr<T> my_ptr(new T); // 正确
unique_ptr<T> my_other_ptr = std::move(my_ptr); // 正确
unique_ptr<T> ptr = my_ptr; // 报错,不能复制

std::make_unique是c++14里加入的标准库,使用unique_ptr,只有一个智能指针管理资源。
参考:https://juejin.cn/post/7137133849430982693

c 和 c++ 中动态分配内存的方式差异

  1. new 是运算符,malloc是函数
  2. new 可以重载,malloc不可以重载
  3. malloc开辟空间失败返回NULL,new 分配空间失败,抛出bac_alloc异常,
    malloc和free是c中的函数,因此在c++中无法执行构造和析构函数。

左右值

左值(lvalue):左值表示了一个占据内存中某个可识别的位置(地址)的对象
右值(rvalue):右值表示了一个不表示内存中某个可识别位置(地址)的对象的表达式

int var;
var = 4;

上面的代码中,var 是一个具有内存位置的对象,他是左值,4 是一个临时变量是一个右值,
左值有内存地址,可以被修改,但是并不是所有的左值都可以被赋值,可以被赋值的左值称为可修改的左值:

const int a = 10; // 'a' 是左值
a = 10;           // 但不可以赋值给它!

例如在上面代码中,a 是一个左值,但是 a 不能被赋值。

https://nettee.github.io/posts/2018/Understanding-lvalues-and-rvalues-in-C-and-C/

不完整类型

incomplete types (types that describe objects but lack information needed to determine their sizes).

不完整类型举例:

class base;
struct test;

这里只给出了 base 和 test 的声明,没有给出定义,不完整类只能用于定义指针或者引用,实例化的是指针或者引用本身,而不是base或者test对象。
位置长度的数组也属于一种不完整类型。

你可能感兴趣的:(c++,开发语言)