上篇文章速通了c语言,但是为了更好地学习数据结构。这里开始浅学一下c++基础(速通版),方法主要是与c对比着学习。
一.基本语法
首先看一段最简单的输入输出程序:
#include <iostream> 头文件
using namespace std;//使用 std 命名空间。命名空间是 C++ 中一个相对新的概念。
// main() 是程序开始执行的地方
int main()
{
cout << "Hello World"; // cout <<,c++的printf
return 0;
}
二.数据类型
c++基本跟c没啥区别,多了布尔数据类型以及宽字符型wchar_t,但实际上的空间是和 short int 一样的。字节大小这不展开说明,详见C++ 数据类型 | 菜鸟教程 (runoob.com);
类型转换:
C++ 中有四种类型转换:静态转换、动态转换、常量转换和重新解释转换。
静态转换:
int i = 10;
float f = static_cast<float>(i); // 静态将int类型转换为float类型
静态转换通常用于比较类型相似的对象之间的转换,缺点是不进行任何运行时类型检查,因此可能会导致运行时错误。
动态转换:
通常用于将一个基类指针或引用转换为派生类指针或引用。动态转换在运行时进行类型检查,如果不能进行转换则返回空指针或引发异常。
class Base {};
class Derived : public Base {};
Base* ptr_base = new Derived;
Derived* ptr_derived = dynamic_cast<Derived*>(ptr_base); // 将基类指针转换为派生类指针
常量转换:
用于将 const 类型的对象转换为非 const 类型的对象。只能用于转换掉 const 属性,不能改变对象的类型。这里const关键字用定义常量,表示该变量的值不能被修改。相当于#define。也有其他的类型限定符,详见C++ 修饰符类型 | 菜鸟教程 (runoob.com)
const int i = 10;
int& r = const_cast<int&>(i); // 常量转换,将const int转换为int
重新解释转换:
将一个数据类型的值重新解释为另一个数据类型的值,通常用于在不同的数据类型之间进行转换。重新解释转换不进行任何类型检查,因此可能会导致未定义的行为。
int i = 10;
float f = reinterpret_cast<float&>(i); // 重新解释将int类型转换为float类型
这里对于加粗的概念不是很了解,我们接着往后看。
三.变量类型
这里直接补充自己不熟悉的东西:
-
指针类型(Pointer Types):
type*
:用于表示指向类型为type
的对象的指针。
-
数组类型(Array Types):
type[]
或type[size]
:用于表示具有相同类型的元素组成的数组。
-
结构体类型(Structure Types):
struct
:用于定义包含多个不同类型成员的结构。
-
类类型(Class Types):
class
:用于定义具有属性和方法的自定义类型。
-
共用体类型(Union Types):
union
:用于定义一种特殊的数据类型,它可以在相同的内存位置存储不同的数据类型。
四.变量作用域:
补充一下类作用域:
#include <iostream>
class MyClass {
public:
static int class_var; // 类作用域变量
};
int MyClass::class_var = 30;//使用类名和作用域解析运算符 :: 来访问这个变量
int main() {
std::cout << "类变量: " << MyClass::class_var << std::endl;
return 0;
}
类变量: 30
c++还提到了存储类这个概念,由于本文重点是了解c++的语言模式,这里不展开记录,直接上链接C++ 存储类 | 菜鸟教程 (runoob.com)
五.函数
在c++中,有三种传参方式,直接口述差别。传值调用只改变形参,不改实参,而指针调用传入的是指针,指向的地址,因此改变形参,实参也会改变(因为实际改变了他们的地址)还有一种就是引用调用,这也是最方便和数据结果伪码中最常用的一种,它的本质是把引用的地址复制给形式参数。和指针调用一样,修改形式参数会影响实际参数。还有一点要注意的是,C++ 默认使用传值调用来传递参数
六.数字
随机数用的比较多,记一下:
关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。生成随机数之前必须先调用 srand() 函数。
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main ()
{
int i,j;
// 设置种子
srand( (unsigned)time( NULL ) );
/* 生成 10 个随机数 */
for( i = 0; i < 10; i++ )
{
// 生成实际的随机数
j= rand();
cout <<"随机数: " << j << endl;
}
return 0;
}
随机数: 1748144778
随机数: 630873888
随机数: 2134540646
随机数: 219404170
随机数: 902129458
随机数: 920445370
随机数: 1319072661
随机数: 257938873
随机数: 1256201101
随机数: 580322989
七.数组
这里我想记录一下从函数中返回数组。实际上c++不用java一样可以直接返回数组,所以可以通过返回一个指向数组的指针实现同样的效果:
int* myFunction()
{
int myArray[3] = {1, 2, 3};
return myArray;
}
这里教程还提醒了:不能简单地返回指向局部数组的指针,因为当函数结束时,局部数组将被销毁,指向它的指针将变得无效。C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。为了避免以上情况,可以使用静态数组或者动态分配数组。
直接上实例;
静态数组
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
// 要生成和返回随机数的函数
int * getRandom( )
{
static int r[10];
// 设置种子
srand( (unsigned)time( NULL ) );
for (int i = 0; i < 10; ++i)
{
r[i] = rand();
cout << r[i] << endl;
}
return r;
}
// 要调用上面定义函数的主函数
int main ()
{
// 一个指向整数的指针
int *p;
p = getRandom();
for ( int i = 0; i < 10; i++ )
{
cout << "*(p + " << i << ") : ";
cout << *(p + i) << endl;
}
return 0;
}
624723190
1468735695
807113585
976495677
613357504
1377296355
1530315259
1778906708
1820354158
667126415
*(p + 0) : 624723190
*(p + 1) : 1468735695
*(p + 2) : 807113585
*(p + 3) : 976495677
*(p + 4) : 613357504
*(p + 5) : 1377296355
*(p + 6) : 1530315259
*(p + 7) : 1778906708
*(p + 8) : 1820354158
*(p + 9) : 667126415
动态分配数组:使用 new 运算符来分配一个数组
#include <iostream>
using namespace std;
int* createArray(int size) {
int* arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
return arr;
}
int main() {
int* myArray = createArray(5);
for (int i = 0; i < 5; i++) {
cout << myArray[i] << " ";
}
cout << endl;
delete[] myArray; // 释放内存
return 0;
}
八.指针
8.1 指针与数组
实际上,数组中存储的是元素的元素,我们从可以下面实例清晰了解:
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
int *ptr;
// 指针中的数组地址
ptr = var;
for (int i = 0; i < MAX; i++)
{
cout << "var[" << i << "]的内存地址为 ";
cout << ptr << endl;
cout << "var[" << i << "] 的值为 ";
cout << *ptr << endl;
// 移动到下一个位置
ptr++;
}
return 0;
}
var[0]的内存地址为 0x7fff59707adc
var[0] 的值为 10
var[1]的内存地址为 0x7fff59707ae0
var[1] 的值为 100
var[2]的内存地址为 0x7fff59707ae4
var[2] 的值为 200
因此我们就不能直接通过数组名修改数组元素
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++)
{
*var = i; // 这是正确的语法
var++; // 这是不正确的
}
return 0;
}
把 var[2] 赋值为 500,正确的方式是。且本身var(地址)不变
*(var + 2) = 500;
8.2 指向指针的指针
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。指针的指针就是将指针的地址存放在另一个指针里面。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
声明为:
int **var;
同样的,还有传递指针给函数(只需要简单地声明函数参数为指针类型即可)以及从函数返回指针(这里就和上面的从函数返回数组是一个道理,一样需要使用静态变量。因为本身数组和指针就非常相似)
九.引用
写完指针,接着记一下引用的知识:
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
#include <iostream>
using namespace std;
int main ()
{
// 声明简单的变量
int i;
double d;
// 声明引用变量
int& r = i;
double& s = d;
i = 5;
cout << "Value of i : " << i << endl;
cout << "Value of i reference : " << r << endl;
d = 11.7;
cout << "Value of d : " << d << endl;
cout << "Value of d reference : " << s << endl;
return 0;
}
Value of i : 5
Value of i reference : 5
Value of d : 11.7
Value of d reference : 11.7
通常的,对于指针变量,&该变量就是返回其地址值,上面说函数调用时,也有引用调用,本质上也是一样的。同样的,也有函数返回引用,用法和函数返回指针差不多,不多说了。见C++ 把引用作为返回值 | 菜鸟教程 (runoob.com)
OK,就先记到这,后面的面向对象实在不想写(本来就是为了速通基本规则),自行学习速通去了。其他的内容就不学了,不走c++(手动狗头)