Android Framework 基础篇 之 C++

C++语法入门

目录

C++语法入门

一、变量和数据类型

二、运算符

三、条件语句

四、循环语句

五、函数

六、类和对象

七、指针

八、数组与字符串

九、文件操作

十、STL(标准模板库)

十一、异常处理

十二、模板

十三、命名空间

十四、操作符重载

十五、面向对象编程的深入

1. 类的访问控制

2. 类的构造函数和析构函数

3. 类的继承

4. 虚函数与多态

十六、模板元编程

十七、C++标准库进阶

1. 标准模板库(STL)

2. I/O流

3. 字符串处理

4. 时间处理

5. 并发与多线程

6. 实用工具

十八、C++设计模式

十九、C++性能优化

二十、C++内存管理

1. 动态内存分配

2. 智能指针

3. 内存泄漏

4. 内存对齐

5. 自定义内存管理

二十一、C++模板元编程进阶

1. 类型特征

2. 模板特化和偏特化

3. 递归模板和编译时计算

二十二、C++网络与多线程编程

1. 网络编程

2.多线程编程

二十三、C++性能分析与调优

1. 性能分析工具

2. 代码优化

3. 并发与并行优化

4. 内存管理优化


C++是一种广泛使用的编程语言,它是C语言的扩展,增加了面向对象的特性。对于初学者来说,掌握C++的基本语法是学习的重要一步。在本文中,我们将介绍C++的一些基本语法,帮助你快速入门。

一、变量和数据类型

在C++中,变量是用来存储数据的标识符。每个变量都有一个数据类型,用来决定它可以存储哪种类型的数据。例如,int用于存储整数,float和double用于存储浮点数,char用于存储字符等。

int a = 10; // 定义一个整数变量a,并赋值为10
float b = 3.14; // 定义一个浮点数变量b,并赋值为3.14
char c = 'A'; // 定义一个字符变量c,并赋值为'A'

二、运算符

C++提供了丰富的运算符,用于执行各种操作,如算术运算、比较运算、逻辑运算等。

int x = 5, y = 10;
int sum = x + y; // 加法运算
bool isEqual = x == y; // 比较运算
bool isGreater = x > y; // 另一个比较运算

三、条件语句

条件语句用于根据条件执行不同的代码块。C++中最常用的条件语句是if-else语句。

int number = 15;
if (number > 10) {
std::cout << "Number is greater than 10." << std::endl;
} else {
std::cout << "Number is not greater than 10." << std::endl;
}

四、循环语句

循环语句用于重复执行一段代码,直到满足某个条件为止。C++提供了多种循环语句,如for循环、while循环和do-while循环。

for (int i = 0; i < 5; i++) {
std::cout << "This is loop iteration " << i + 1 << std::endl;
}

五、函数

函数是一段可以重复使用的代码,它接受一些输入(参数),执行一些操作,并可能返回一个值。

int add(int a, int b) {
return a + b;
}
int main() {
int sum = add(5, 3);
std::cout << "Sum is: " << sum << std::endl;
return 0;
}

在上面的例子中,我们定义了一个名为add的函数,它接受两个整数作为参数,并返回它们的和。然后在main函数中,我们调用了这个函数,并将结果打印出来。

六、类和对象

C++是一种面向对象的编程语言,因此类和对象是C++中的重要概念。类是对对象的抽象描述,它定义了对象的属性和方法。对象是类的实例。

class Rectangle {
private:
double width;
double height;
public:
Rectangle(double w, double h) {
width = w;
height = h;
}
double getArea() {
return width * height;
}
};
int main() {
Rectangle rect(10.0, 5.0);
std::cout << "Area of rectangle is: " << rect.getArea() << std::endl;
return 0;
}

在上面的例子中,我们定义了一个名为Rectangle的类,它有两个私有属性width和height,以及一个公共方法getArea用于计算矩形的面积。然后在main函数中,我们创建了一个Rectangle对象,并调用了它的getArea方法来计算面积。

七、指针

指针是C++中的一个重要概念,它存储了一个变量的内存地址。通过指针,我们可以直接访问和操作内存中的数据。

int x = 10;
int* ptr = &x; // ptr指向x的内存地址
std::cout << "Value of x: " << *ptr << std::endl; // 通过指针访问x的值

指针可以用于动态内存分配、数组操作、函数参数传递等多种场景,但使用指针时也需要格外小心,以避免出现内存泄漏、野指针等问题。

八、数组与字符串

数组是一种用于存储相同类型元素的线性数据结构。在C++中,我们可以定义固定大小的数组,并使用索引来访问数组中的元素。

int arr[5] = {1, 2, 3, 4, 5};
std::cout << "Element at index 2: " << arr[2] << std::endl;

字符串在C++中可以通过字符数组来表示,也可以使用标准库中的std::string类来更方便地操作字符串。

char str[] = "Hello, World!";
std::string str2 = "Another string";
str2 += " appended!"; // 使用string类的成员函数来操作字符串

九、文件操作

C++提供了丰富的文件操作功能,允许我们读取和写入文件。这通常通过std::ifstream(用于输入文件)和std::ofstream(用于输出文件)等流类来实现。

#include <fstream>
int main() {
std::ofstream outfile("example.txt");
if (outfile.is_open()) {
outfile << "This is an example text." << std::endl;
outfile.close();
} else {
std::cout << "Unable to open file";
}
std::ifstream infile("example.txt");
std::string line;
if (infile.is_open()) {
while (getline(infile, line)) {
std::cout << line << std::endl;
}
infile.close();
} else {
std::cout << "Unable to open file";
}
return 0;
}

十、STL(标准模板库)

C++标准模板库(STL)提供了一系列高效的模板类和函数,用于执行常见的数据结构和算法操作。STL包括容器(如vector、list、map等)、迭代器、算法等。

#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {4, 2, 9, 6, 5, 1, 8, 3, 7};
std::sort(vec.begin(), vec.end()); // 使用STL算法对vector进行排序
for (int num : vec) {
std::cout << num << " ";
}
return 0;
}

STL的使用可以大大提高代码的可读性和可维护性,同时提供了高效的数据结构和算法实现。

十一、异常处理

C++中的异常处理是一种错误处理机制,它允许程序在运行时检测和处理异常情况。通过try-catch块,我们可以捕获并处理可能发生的异常。

try {
// 代码块,可能抛出异常
throw std::runtime_error("An error occurred");
} catch (const std::runtime_error& e) {
// 处理异常
std::cerr << "Caught an exception: " << e.what() << std::endl;
}

异常处理可以使代码更加健壮,能够优雅地处理错误情况,而不是简单地崩溃或返回错误码。

十二、模板

模板是C++中实现泛型编程的一种机制。通过模板,我们可以编写与类型无关的代码,然后在需要时指定具体的类型。这有助于减少代码冗余,提高代码的可重用性。

template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
int sum = add<int>(5, 3); // 调用模板函数,指定类型为int
double dsum = add<double>(2.5, 1.5); // 调用模板函数,指定类型为double
std::cout << "Int sum: " << sum << std::endl;
std::cout << "Double sum: " << dsum << std::endl;
return 0;
}

十三、命名空间

随着程序规模的增大,命名冲突的问题可能会变得越来越突出。C++中的命名空间(namespace)提供了一种将相关的类、函数和变量组织在一起的方式,从而避免了命名冲突。

namespace MyNamespace {
int x = 10;
void printX() {
std::cout << "Value of x in MyNamespace: " << x << std::endl;
}
}
int main() {
int x = 20;
std::cout << "Value of x in main: " << x << std::endl;
MyNamespace::printX(); // 使用命名空间前缀来访问MyNamespace中的printX函数
return 0;
}

在上面的例子中,我们定义了一个名为MyNamespace的命名空间,并在其中声明了一个变量x和一个函数printX。在main函数中,我们定义了一个同名的变量x,但通过使用命名空间前缀MyNamespace::,我们可以清晰地指定要调用哪个命名空间中的函数或变量。

十四、操作符重载

C++允许我们重新定义或“重载”现有的操作符,以便它们可以用于用户定义的类型。这使得我们可以以更自然和直观的方式操作这些类型。

class Complex {
private:
double real;
double imag;
public:
Complex(double r, double i) : real(r), imag(i) {}
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
void print() const {
std::cout << "(" << real << ", " << imag << ")" << std::endl;
}
};
int main() {
Complex c1(1.0, 2.0);
Complex c2(3.0, 4.0);
Complex sum = c1 + c2; // 使用重载的+操作符来计算两个复数的和
sum.print(); // 输出结果
return 0;
}

十五、面向对象编程的深入

C++是一种支持面向对象编程(OOP)的语言,OOP是一种编程范式,它使用“对象”来设计应用程序和软件。对象包含数据和操作这些数据的方法。在C++中,类是实现OOP的基础。

1. 类的访问控制

在C++中,类的成员可以有三种访问级别:公有(public)、保护(protected)和私有(private)。公有成员可以在类的外部被访问,私有成员只能在类的内部被访问,而保护成员则可以在类的内部和派生类中被访问。

class MyClass {
private:
int privateVar; // 私有成员变量
protected:
int protectedVar; // 保护成员变量
public:
int publicVar; // 公有成员变量
void setPrivateVar(int value) { privateVar = value; } // 设置私有变量的公有方法
void printVars() {
std::cout << "Private: " << privateVar << std::endl;
std::cout << "Protected: " << protectedVar << std::endl;
std::cout << "Public: " << publicVar << std::endl;
}
};

2. 类的构造函数和析构函数

构造函数是一种特殊的成员函数,当创建类的对象时,它会自动被调用。析构函数也是特殊的成员函数,当对象的生命周期结束时,它会自动被调用。

class MyClass {
private:
int x;
public:
MyClass(int val) : x(val) { // 构造函数
std::cout << "Object created with value: " << x << std::endl;
}
~MyClass() { // 析构函数
std::cout << "Object destroyed" << std::endl;
}
};

3. 类的继承

继承是面向对象编程中的一个重要概念,它允许我们创建一个新的类(派生类),继承另一个类(基类)的属性和方法。

class Base {
public:
void show() { std::cout << "Base class" << std::endl; }
};
class Derived : public Base { // 继承Base类
public:
void display() { std::cout << "Derived class" << std::endl; }
};
int main() {
Derived d;
d.show(); // 调用继承自Base类的方法
d.display(); // 调用Derived类自己的方法
return 0;
}

4. 虚函数与多态

虚函数和多态是C++中实现动态绑定的重要机制。通过虚函数,我们可以在基类中声明一个函数,并在派生类中重写它。多态允许我们在运行时确定要调用哪个版本的函数。

 
class Base {
public:
virtual void show() { std::cout << "Base class show" << std::endl; }
};
class Derived : public Base {
public:
void show() override { std::cout << "Derived class show" << std::endl; }
};
void display(Base* b) { // 接受基类指针的函数
b->show(); // 在运行时决定调用哪个show()方法
}
int main() {
Base* basePtr = new Base();
Derived* derivedPtr = new Derived();
display(basePtr); // 输出 "Base class show"
display(derivedPtr); // 输出 "Derived class show",多态的体现
delete basePtr;
delete derivedPtr;
return 0;
}

十六、模板元编程

模板元编程(TMP)是C++中一种利用模板在编译时进行类型操作和计算的技术。它允许程序员在编译时执行复杂的元操作,从而优化程序性能或实现一些无法在运行时完成的任务。

template<typename T, T Value>
struct Constant {
static const T value = Value;
};
int main() {
const int c = Constant<int, 5>::value; // 在编译时计算常量值
std::cout << c << std::endl; // 输出 5
return 0;
}

在上面的例子中,我们定义了一个模板结构体Constant,它接受一个类型和一个值作为模板参数。在结构体内部,我们定义了一个静态常量成员value,它的值等于模板参数Value。这样,我们就可以在编译时计算出常量的值,并在程序中使用它。

十七、C++标准库进阶

C++标准库是一个庞大的集合,包含了大量的容器、迭代器、算法、I/O流和其他实用工具。熟练掌握这些库可以帮助我们更加高效地进行C++编程。

1. 标准模板库(STL)

STL是C++标准库中的一部分,提供了一系列泛型容器、迭代器以及算法,使得我们可以更方便地处理数据。

容器

  • vector:动态数组,可以方便地添加和删除元素。
  • list:双向链表,可以在任意位置插入和删除元素。
  • deque:双端队列,支持在两端快速插入和删除元素。
  • set 和 multiset:有序集合,自动对元素进行排序。
  • map 和 multimap:键值对集合,可以根据键快速查找对应的值。

迭代器
迭代器是STL中用于遍历容器元素的工具。不同类型的容器有不同的迭代器类型,但所有迭代器都支持一些基本操作,如解引用、递增和递减等。

算法
STL提供了大量的算法,用于对容器中的元素进行各种操作,如排序、查找、复制等。这些算法通常与迭代器一起使用,使得我们可以对任意类型的容器进行操作。

2. I/O流

C++标准库中的I/O流提供了一种方便的方式来处理输入和输出。通过I/O流,我们可以从文件、控制台或其他设备读取数据,也可以将数据写入这些设备。

文件操作
使用ifstreamofstreamfstream类可以方便地打开、读取和写入文件。这些类提供了类似于C语言文件操作的接口,但更加安全和易用。

格式化输出
通过std::cout和格式化操作符(如<<),我们可以将各种类型的数据以特定的格式输出到控制台或文件中。

格式化输入
使用std::cin和格式化操作符(如>>),我们可以从控制台或文件中读取各种类型的数据。

3. 字符串处理

C++标准库中的<string>头文件提供了一系列用于处理字符串的类和函数。

std::string
这个类用于表示和操作字符串。它支持各种操作,如连接、查找、替换等。

字符串算法
标准库还提供了一些字符串算法,如分割字符串、比较字符串等。这些算法可以大大提高我们处理字符串的效率。

4. 时间处理

<chrono>头文件是C++11及以后版本中引入的一个强大的时间库,它提供了高精度的时间点和时间间隔的表示和处理。我们可以使用它来测量程序的执行时间、处理日期和时间等。

5. 并发与多线程

C++11及以后的版本引入了对并发和多线程的原生支持。通过<thread><mutex><condition_variable>等头文件,我们可以编写出高效且安全的并发程序。

6. 实用工具

标准库还包含了许多实用工具,如智能指针(用于管理动态内存)、随机数生成器、函数对象等。这些工具可以帮助我们编写更加健壮和高效的代码。

十八、C++设计模式

设计模式是在软件开发中解决常见问题的最佳实践。掌握设计模式可以使我们的代码更加灵活、可维护和可扩展。C++中常用的设计模式包括:

  1. 单例模式:确保一个类只有一个实例,并提供一个全局访问点。
  2. 工厂模式:创建对象的最佳方式,隐藏了对象的具体实现细节。
  3. 观察者模式:定义对象之间的一对多依赖关系,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
  4. 迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
  5. 策略模式:定义一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于使用它的客户变化。

这只是C++设计模式的冰山一角,实际上还有更多的设计模式等待你去探索和学习。

十九、C++性能优化

性能优化是编程中不可或缺的一部分。了解如何优化C++代码可以帮助我们编写出更加高效的应用程序。以下是一些常见的性能优化技巧:

  1. 减少不必要的对象复制:使用引用和指针来传递大型对象,避免不必要的复制操作。
  2. 选择合适的数据结构和算法:根据问题的特性选择合适的数据结构和算法,以提高程序的执行效率。
  3. 利用缓存优化:合理地利用CPU缓存和内存局部性原理,减少缓存未命中的次数。
  4. 避免不必要的内存分配和释放:合理使用智能指针和内存池等技术,减少内存分配和释放的次数。

二十、C++内存管理

内存管理是C++编程中至关重要的一部分,它涉及到如何有效地分配和释放内存,以及如何避免常见的内存问题,如内存泄漏、野指针和悬挂指针等。

1. 动态内存分配

C++使用newdelete操作符进行动态内存分配和释放。通过new,我们可以在运行时动态地创建对象,并返回指向该对象的指针。而delete则用于释放通过new分配的内存。

int* ptr = new int(5); // 动态分配内存并初始化为5
*ptr = 10; // 修改内存中的值
delete ptr; // 释放内存
ptr = nullptr; // 避免悬挂指针

2. 智能指针

为了简化内存管理并减少内存泄漏的风险,C++11引入了智能指针。智能指针是存储指针的类,它会在适当的时候自动删除它所指向的对象。常见的智能指针包括std::unique_ptrstd::shared_ptrstd::weak_ptr

std::unique_ptr<int> smartPtr(new int(5)); // 使用unique_ptr管理内存
// 当smartPtr离开作用域时,它会自动删除所指向的int对象

3. 内存泄漏

内存泄漏是指程序在申请内存后,未能释放已申请的内存空间,导致系统内存的浪费,严重时会导致程序崩溃。为了避免内存泄漏,程序员应该确保每个通过new分配的内存块最终都被delete释放。使用智能指针可以大大减少内存泄漏的风险。

4. 内存对齐

内存对齐是编译器为了提高数据访问效率而采取的一种策略。编译器会按照特定规则对变量在内存中的位置进行调整,使得数据的读取和写入更加高效。了解内存对齐的原理和规则可以帮助程序员写出更加高效的代码。

5. 自定义内存管理

在某些特殊情况下,可能需要自定义内存管理策略,以满足特定的性能或资源需求。这通常涉及到重载newdelete操作符,或者使用专门的内存分配器。

二十一、C++模板元编程进阶

模板元编程是一种在编译时执行类型级别计算的强大技术。通过模板元编程,我们可以在编译时生成高效的代码,甚至实现一些无法在运行时完成的任务。

1. 类型特征

类型特征是模板元编程中的一个重要概念,它允许我们在编译时查询类型的属性。C++标准库提供了一系列类型特征模板,如std::is_samestd::is_integral等,用于判断类型的性质。

template<typename T>
void foo() {
if constexpr (std::is_integral<T>::value) {
// T是整型时的处理逻辑
} else {
// T不是整型时的处理逻辑
}
}

2. 模板特化和偏特化

模板特化允许我们为特定的类型或模板参数集合提供专门的实现。偏特化则是对模板特化的扩展,允许我们基于部分模板参数提供特化实现。

template<typename T>
struct MyTemplate {
// 通用实现
};
template<>
struct MyTemplate<int> {
// int类型的特化实现
};
template<typename T1, typename T2>
struct MyTemplate2 {
// 通用实现
};
template<typename T>
struct MyTemplate2<T*, int> {
// 针对T*和int的偏特化实现
};

3. 递归模板和编译时计算

递归模板允许我们在编译时进行递归计算。通过递归模板,我们可以实现一些复杂的编译时算法,如编译时阶乘、斐波那契数列等。

template<int N>
struct Factorial {
static constexpr int value = N * Factorial<N - 1>::value;
};
template<>
struct Factorial<0> {
static constexpr int value = 1;
};
int main() {
constexpr int fiveFactorial = Factorial<5>::value; // 编译时计算5的阶乘
return 0;
}

二十二、C++网络与多线程编程

随着多核CPU的普及和互联网的发展,网络和多线程编程成为现代C++应用程序中不可或缺的一部分。

1. 网络编程

C++提供了套接字(socket)编程接口,用于实现网络通信。通过套接字,我们可以创建服务器和客户端应用程序,实现数据的发送和接收。

#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

// 创建一个简单的TCP服务器
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
// 创建socket文件描述符
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 设置socket选项
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
// 绑定socket到指定的地址和端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 开始监听连接
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 在这里处理客户端请求和发送响应...
// 关闭socket
close(new_socket);
close(server_fd);
return 0;
}

2.多线程编程

C++11及以后的版本提供了对多线程的原生支持,通过`<thread>`头文件,我们可以方便地创建和管理线程。多线程编程可以充分利用多核CPU的计算能力,提高程序的并发性能。

```cpp
#include <iostream>
#include <thread>
#include <vector>
// 线程函数
void threadFunction(int id) {
std::cout << "Thread " << id << " is running." << std::endl;
// 执行线程任务...
}
int main() {
std::vector<std::thread> threads;
// 创建多个线程
for (int i = 0; i < 5; ++i) {
threads.emplace_back(threadFunction, i);
}
// 等待所有线程完成
for (auto& thread : threads) {
thread.join();
}
return 0;
}

在多线程编程中,还需要注意线程同步和互斥的问题,以避免数据竞争和死锁等问题。C++提供了互斥锁(std::mutex)、条件变量(std::condition_variable)等同步原语来帮助我们管理线程间的同步。

二十三、C++性能分析与调优

性能分析和调优是软件开发中不可或缺的一部分。对于C++程序来说,了解其性能瓶颈并进行相应的优化可以显著提高程序的执行效率。

1. 性能分析工具

使用性能分析工具可以帮助我们识别程序的性能瓶颈。常见的C++性能分析工具包括gprofValgrindcallgrind工具、perf等。这些工具可以收集程序的运行时信息,如函数调用关系、CPU使用率、内存使用情况等,从而帮助我们找到性能问题所在。

2. 代码优化

针对性能分析工具提供的信息,我们可以对代码进行优化。优化手段包括但不限于:

  • 减少不必要的对象复制和内存分配。
  • 选择合适的数据结构和算法。
  • 利用缓存优化数据访问模式。
  • 减少锁的竞争和等待时间。
  • 使用编译器优化选项。

3. 并发与并行优化

对于可以并行处理的任务,我们可以利用多线程或异步编程来提高程序的并发性能。通过合理划分任务、使用线程池、避免线程间的频繁通信等手段,可以进一步提高程序的执行效率。

4. 内存管理优化

优化内存管理也是提高C++程序性能的重要手段。我们可以通过减少内存碎片、避免内存泄漏、使用内存池等技术来优化内存的使用。

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值