其實就是四驅模型的拷貝,引用實際上是地址賦值,能夠當作同一塊內存的另一個變量 以兩個變量值交換爲例html
#include<stdio.h>
void swap(int &number1, int &number2) {
// &number 此處至關於同一塊內存 取了另外一個別名
int temp = number1;
number1 = number2;
number2 = temp;
}
void main() {
int number1 = 10;
int number2 = 20;
swap(number1, number2);
printf("%d %d\n", number1, number2); // 結果 20 10
getchar();
}
複製代碼
常量變量:被常量修飾的變量,不能再次被賦值 (Java)java
常量指針(const int *p):const 在 * 以前,指針的地址是能夠被再次賦值的(能夠修改的),指針地址上面的值(變量)是不能被修改的,常量指針的常量是不能被改變的。指向常量的指針,表示不能夠修改p的內容,可是能夠修改 p 的地址.ios
指針常量(int *const p):const 在 * 以後,指針的地址是不能夠被再次賦值的(不能夠修改的),指針地址上面的值(變量)能被修改的,指針常量的指針地址是不能被改變的。指針的常量,表示不能夠修改p的地址,可是能夠修改 p 的內容.c++
// 常量,不能去修改
const int number = 100;
// number = 200; // error
int number1 = 100;
int number2 = 200;
// 常量指針
// int const * n_p = &number2;
// n_p = &number1;
// printf("n_p = %p",n_p); // 地址是能夠從新被賦值的
// *n_p = 300; // 值是不能改的 error
// 指針常量
int * const n_p = &number2;
// n_p = &number1; // 地址是不能被從新賦值
*n_p = 300;
printf("number2 = %d", number2);// 值能夠被修改,結果:300
複製代碼
malloc/free 一對,new/delete 是一對程序員
malloc/free 不會去調用構造函數和析構函數算法
new/delete 會去調用構造函數和析構函數 若是用了new,必定要記得 delete 釋放內存安全
直接上代碼說明bash
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
class Student
{
public:
// 構造函數
Student(){// 空參數構造函數
cout << "空參數構造函數"<< endl;
}
// Student(char* name):age(0){// 一個參數構造函數, 至關於 this->age = 0
// cout << "一個參數構造函數" << endl;
// this->name = name;
// }
Student(char* name) :Student(name,0){
// 調用兩個參數的構造函數
// 注意:先會調用兩個參數的構造函數,而後纔會執行當前構造函數
cout << "一個參數構造函數" << endl;
}
Student(char* name, int age){// 兩個參數構造函數
cout << "兩個參數構造函數" << endl;
this->name = (char*)malloc(sizeof(char)*100);
strcpy(this->name,name);
this->age = age;
}
// 2. 析構函數,若是有在對象內部開闢堆內存,能夠在析構函數中釋放內存
~Student(){
cout << "析構函數" << endl;
// 對象被回收的時候會被調用
// 釋放內存
free(this->name);
this->name = NULL;
}
/*
4.拷貝構造函數,在 java 中若是 Student stu2 = stu1,那麼咱們通常會認爲 stu2 對象和 stu1 對象是同一個對象,
可是在 c++ 中這種認爲就是錯誤的,咱們能夠分別打印 stu1 和 stu2 的地址發現並不相等,
因此 stu1 和 stu2 並非同一個對象,而是會調用拷貝構造函數。*/
// 對象會有一個默認的拷貝構造函數,用來對象之間的賦值
Student(const Student& stu){// 常量的引用
cout << "拷貝構造函數" << endl;
// this->name = stu.name;// 淺拷貝
// 若是動態開闢內存,必定要採用深拷貝
this->name = (char*)malloc(sizeof(char)* 100);
strcpy(this->name, stu.name);
this->age = stu.age;
}
Student getStudent(char* name){
Student stu(name);// 棧 ,方法執行完,這個對象會被回收,可是發現調用了拷貝構造函數
cout << &stu << endl;
return stu;// 會返回一個新的 Student 對象,而棧內開闢的 stu 是會被回收
}
void printStudent(Student stu){// stu 是該方法棧中一個新的對象,拷貝構造函數賦值,方法執行完會調用析構函數
cout << stu.getName() << " , " << stu.getAge() << endl;
}
void main(){
// 1. = 會調用拷貝構造函數
// Student stu1("Darren", 24);
// Student stu2 = stu1; // = 是賦值,把裏面全部定義的屬性賦值,c/c++ 編譯器幫咱們作的,其實會調用對象的拷貝構造
// Student stu2;// 聲明變量,開闢變量內存
// stu2 = stu1; // 這個不會去調用拷貝構造函數,可是會賦值 c 的相似
// 2. 第二種場景 做爲參數返回的時候會調用拷貝構造函數
// Student stu = getStudent("Jack");
// cout << &stu << endl;
// 3. 第三種場景 做爲參數傳遞的時候會調用拷貝構造函數
// Student stu("Darren", 24);
// printStudent(stu);
// 知識的補充
Student stu = getStudent("Jack");
// cout << stu.getName() << " , " << stu.getAge() << endl;
printStudent(stu);
getchar();
}
private:
int age;
char* name;
public:
int getAge(){
return this->age;
}
char* getName(){
return this->name;
}
void setAge(int age){
this->age = age;
}
void setName(char* name){
this->name = name;
}
};
複製代碼
在 c/c++ 中咱們將運行時數據,分爲四個區域分別是:棧區,堆區,數據區,代碼區。咱們詳細來介紹下:數據結構
#include <iostream>
#include <stdarg.h>
using namespace std;
int sum(int count, ...) { // 格式:count表明參數個數, ...表明n個參數
va_list ap; // 聲明一個va_list變量
va_start(ap, count); // 第二個參數表示形參的個數
int sum = 0;
for (int i = 0; i < count; i++) {
sum += va_arg(ap, int); // 第二個參數表示形參類型
}
va_end(ap); // 用於清理
return sum;
}
void main(){
int sumValue = sum(3,8,10,9);
cout << sumValue << endl; // 輸出結果:27
getchar();
}
複製代碼
步驟:
app
定義頭文件 stdarg.h
定義參數:參數格式 (int count, ...)
函數定義中建立一個 va_list 變量
初始化: va_start(ap, count);
循環將各個參數進行相加
清理:調用清理 va_end(va_list); 清理內容,最後調用
class Test {
public static int tag;
}
int Test::tag = 1; // 只能這樣初始化
複製代碼
類中只計算除了靜態屬性的大小之和,方法什麼的都不算,但定義字節數大的要排在字節數小的,例如 double 屬性要在 int 以前,若定義不按此規則,則類的大小可能會變大,這樣作有利於提升性能
友元函數
class A{
// 友元函數聲明
friend void modify_i(A *p, int a);
private:
int i;
public:
A(int i){
this->i = i;
}
void myprint(){
cout << i << endl;
}
};
// 友元函數的實現
void modify_i(A *p, int a){
p->i = a;
}
void main(){
A* a = new A(10);
a->myprint();
modify_i(a,20);
a->myprint();
}
複製代碼
友元類
class A{
// 友元類聲明,表示 B 這個友元類能夠訪問 A 類的任何成員
friend class B;
private:
int i;
public:
A(int i){
this->i = i;
}
void myprint(){
cout << i << endl;
}
};
class B{
private:
A a;
public:
void accessAny(){
a.i = 30;
}
};
複製代碼
至關於 Java 的抽象,解決繼承二義性問題
virtual
關鍵字,確保繼承過來的相同屬性或者函數,只存在一份拷貝
class A{
public:
char* name;
};
class B : virtual public A{ // 確保繼承過來的相同屬性或者函數,只存在一份拷貝
};
class C :virtual public A{
};
class D : public B ,public C
{
};
複製代碼
至關於 Java 的泛型
template <typename T>// 模板函數的定義
T add(T number1, T number2){
return number1 + number2;
}
void main(){
int sum1 = add(1,2);
cout << sum1 << endl;
int sum2 = add(1.0, 2.0);
cout << sum2 << endl;
int sum3 = add(1.0f, 2.0f);
cout << sum3 << endl;
getchar();
}
複製代碼
當同名普通函數和模板函數同時存在的時候,優先會調用普通函數
例:父類(Person)轉子類(Student)
// 1.static_cast,通常用於轉換有繼承關係的類型
Student *student = static_cast<Student*>(person);
// 2.reinterpret_cast,除了字符類型,各類類型的轉換,經常使用
Student *student = reinterpret_cast<Student*>(person);
複製代碼
// string 轉 char*
string str = "666";
const char* str2char = str.c_str();
// char* 轉 string
char* char2str = "666"
string strValue(char2str);
複製代碼
string str("1234567");
// 1. 字符串的遍歷
for (int i = 0; i < str.length(); i++)
{
cout << str[i] << endl;
// or
cout << str.at(i) << endl;
}
// 2. 迭代器遍歷
for (string::iterator it = str.begin(); it < str.end(); it++)
{
cout << *it << endl;
}
複製代碼
添加
string str1 = "123";
string str2 = "456";
str1 = str1 + str2;
str1.append(str2);
複製代碼
刪除
string str1 = "123456789";
// 第一個參數:從哪裏開始 ; 第二個參數:刪除幾個(默認值,字符串的結尾)
str1.erase(0, 3);
// 迭代器刪除
for (string::iterator it = str1.begin(); it<str1.begin() + 3; it++)
{
// 刪除一個字後都會從頭開始計算
str1.erase(it);
}
複製代碼
替換
string str1 = "123456789";
// 第一個參數:從哪裏開始
// 第二個參數:替換幾個
// 第三個參數:替換成誰
str1.replace(0, 6, "0000");
// 結果:前六個替換成 0000
複製代碼
查找
string str1 = "123abc123abc123";
// (查找誰,從哪裏開始),查不到返回 -1
// int position = str1.find("123",0);
// 從後面往前面查
int position = str1.rfind("123");
複製代碼
#define D_SCL_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>// STL 算法包
#include <cctype> // 用到一個函數指針,回調函數
string str1 = "AAA abc BBB abc 123";
// 轉換成大寫
transform(str1.be gin(), str1.end(), str1.begin(), toupper);
// 轉換成小寫
transform(str1.begin(), str1.end(), str1.begin(), tolower);
複製代碼
// 其實引用本質就是 指針
void change(int& number1){// 至關於 c 的 change(int* number1)
number1 = 12;// 至關於 c 的 *number1 = 12;
}
複製代碼
void main(){
int a = 10;
// &是C++中的引用,引用:變量的另一個別名,共用同個地址
int &b = a;
cout << b << endl;
}
複製代碼
struct Teacher{
char* name;
int age;
};
// 帶有結構體指針的寫法
void myprint(Teacher *t){
cout << t->name << "," << t->age << endl;
//(*t).name
}
// 帶有結構體引用的寫法
void myprint2(Teacher &t){
cout << t.name << "," << t.age << endl;
t.age = 21;
}
// 指針值交換
void swap_1(int *a, int *b){
int c = 0;
c = *a;
*a = *b;
*b = c;
}
// 引用值交換
void swap_2(int &a, int &b){
int c = 0;
c = a;
a = b;
b = c;
}
void main(){
Teacher t;
t.name = "Vegen";
t.age = 24;
// 指針的寫法
myprint(&t);
// 引用的寫法
myprint2(t);
int x = 10;
int y = 20;
// 指針的寫法
swap_1(&x, &y);
// 引用的寫法
swap_2(x,y);
}
複製代碼
struct Teacher{
char* name;
int age;
};
// 引用的寫法
void getTeacher(Teacher* &p){
p = (Teacher*)malloc(sizeof(Teacher));
p->age = 24;
}
// 二級指針的寫法,本來應該這樣寫,可是已經被上面引用的寫法代替了
void getTeacher(Teacher **p){
Teacher *tmp = (Teacher*)malloc(sizeof(Teacher));
tmp->age = 24;
*p = tmp;
}
void main(){
Teacher *t = NULL;
//傳遞引用的指針t,至關於二級指針
getTeacher(&t);
}
複製代碼
// 常引用在方法中的引用
void myprint(const int &a){
cout << a << endl;
}
void main(){
// 引用必需要有值,不能爲空,下面寫法是錯誤的
//const int a;
//int &a = NULL;
// 常引用屬性使用一
int a = 10, b = 9;
const int &c = a;
// 常引用屬性使用二
const int &d = 70;
}
複製代碼
struct Teacher{
char name[20];
int age;
};
void main(){
Teacher t;
// 引用
Teacher &t1 = t;
// 指針
Teacher *p = &t;
// 結果是 24,引用至關於變量的別名
cout << sizeof(t1) << endl;
// 結果是 4,指針只是存放的地址
cout << sizeof(p) << endl;
system("pause");
}
複製代碼
class Point{
public:
int x;
int y;
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
void myprint(){
cout << x << "," << y << endl;
}
};
// 重載 + 號
Point operator+(Point &p1, Point &p2){
Point tmp(p1.x + p2.x, p1.y + p2.y);
return tmp;
}
// 重載 - 號
Point operator-(Point &p1, Point &p2){
Point tmp(p1.x - p2.x, p1.y - p2.y);
return tmp;
}
void main(){
Point p1(10,20);
Point p2(20,10);
Point p3 = p1 + p2;
// 輸出結果 30,30
p3.myprint();
}
複製代碼
class Point{
public:
int x;
int y;
public:
Point(int x = 0, int y = 0){
this->x = x;
this->y = y;
}
// 成員函數,運算符重載
Point operator+(Point &p2){
Point tmp(this->x + p2.x, this->y + p2.y);
return tmp;
}
void myprint(){
cout << x << "," << y << endl;
}
};
void main(){
Point p1(10, 20);
Point p2(20, 10);
// 運算符的重載,本質仍是函數調用
//p1.operator+(p2)
Point p3 = p1 + p2;
p3.myprint();
}
複製代碼
持續更新中...