C++ 语法基础(三)(二)

简介: C++ 语法基础(三)(二)

指针数组

知识点


数组名其实就是指向数组第0个元素的指针。但是,不能修改“数组名”这个指针的值,即它是常量指针。

int a[] = {1, 2, 3};
*a; // 等同于a[0]
*(a + n); // 等同于a[n]
int *p = a + 1; 
*p; // 2
*(p + 1); // 3


image.png



知识点


当指针指向数组元素时,加减法才有意义。


可以对指针加上或者减去一个整数。这表示:将指针在数组中向前或向后移动若干位置。


当两个指针指向同一个数组时,可以对两个指针做减法。这表示两个指针所指向元素在数组中的距离。


p = p + 1; // *p == 3
p = p - 1; // *p == 2
cout << p - a << endl; // 1
指针在偏移后不能超过数组的范围。当对超过数组范围的指针解引用时,行为未定义(可能出现运行时错误)。
同样,也不要对不在同一个数组内的两个指针执行减法。
//题目描述:
//实现函数`productMinMax`,返回数组中最小值和最大值的积。
//保证结果不会超过int范围。
//输入:无
//输出:`-90`
#include <iostream>
int productMinMax(int *arr, int len)
{
    int minV = *arr, maxV = *arr;
    for (int *p = arr + 1; p < arr + len; ++p)
    {
        if (minV > *p) minV = *p;
        if (maxV < *p) maxV = *p;
    }
    return minV * maxV;
}
int main()
{
    int arr[] {1, 5, -4, 3, 2, 10, -3, -9, -8};
    std::cout << productMinMax(arr, sizeof(arr) / sizeof(int)) << std::endl;
}


image.png


动态内存分配

知识点


new Type在堆(程序的静态存储区)上新建一个对象,返回指向这个对象的指针。


new Type[cnt] 在堆上新建一个长为cnt,类型为Type的数组,返回这个数组的首指针。


new运算符的初始化:


int *p1 = new int; // *p1为不确定的任意值

int *p2 = new int(3); // *p1 == 3

int *p3 = new int(); // *p1 被初始化为0

int *p4 = new int[4]; // p4数组的所有元素为不确定值

int *p5 = new int[4] {1, 2, 3, 4}; // 用花括号列表初始化

int *p6 = new int[4] (); // p6数组的所有元素被初始化为0

int *p7 = new int[4] {1}; // 注意:p7数组仅有第0个元素为1;其余元素都被初始化为0

无论如何,不建议依赖上文中“初始化为0”的语法,这会增加debug的难度。所有new得到的元素应该被显式初始化。


delete ptr 和 delete ptr[] 可以释放ptr对应的内存。


如果ptr并不指向 new 的内存,程序会发生运行时错误

如果已经 new 的内存未被 delete,则发生内存泄漏

当new操作失败(如系统内存耗尽),它返回nullptr。使用new时建议检测是否成功。


image.png


image.png

动态变量实例

知识点


使用传统的数组,我们只能在源代码中就写好数组的大小,不能修改;


通过申请动态数组,我们可以在运行时控制数组的大小。

image.png

指针与字符串

知识点


字符串也是储存在数组中的。可以把字符串常量赋值给数组来初始化。


由于字符串的最后一个字节一定为'\0',只要得到数组的首指针,就可以遍历整个字符串。

char ss[] = "abc", *str = ss; 
char *str1 = new char[10]; 
strcpy(str1, "abc");
//输出ss,等价于cout << ss << endl;
for (char *p = ss; *p != 0; ++p) 
{
    cout << *p;
}
cout << endl;

也可以把字符串常量赋给 const char* 指针。因为字符串常量的每一个字符不可以修改,使用了 const 修饰符。但这是较陈旧的用法,不建议使用。如果不使用 const,严格说是错误的(编译器会提示warning,但可以运行),此时若修改字符串的任一位,行为未定义(undefined)。

const char *s1 = "hello"; // ok, deprecated
char *s2 = "world"; // warning: ISO C++ forbids converting a string constant to ‘char*’
//题目描述:
//实现函数`myStrcmp`,比较两个输入的字符串。
//如果第一个字符串字典序小于第二个,返回-1;如果字典序相同,返回0;如果第一个字符串字典序大于第二个,返回1。
//输入:无
//输出:`-1`
#include <iostream>
int myStrcmp(const char *s1, const char *s2)
{
    while (*s1 && *s2)
    {
        if (*s1 < *s2)
        {
            return -1;
        } 
        else if (*s1 > *s2)
        {
            return 1;
        }
        s1++;
        s2++;
    }
    if (*s1)
    {
        return 1;
    } 
    else if (*s2)
    {
        return -1;
    } 
    else
    {
        return 0;
    }
}
int main()
{
    char s1[] = "abcde", s2[] = "abcef";
    std::cout << myStrcmp(s1, s2) << std::endl;
}


相关文章
|
3月前
|
Java C# C++
C++ 11新特性之语法甜点1
C++ 11新特性之语法甜点1
33 4
|
3月前
|
编译器 C++ 容器
C++ 11新特性之语法甜点2
C++ 11新特性之语法甜点2
30 1
|
3月前
|
存储 算法 编译器
C++ 11新特性之语法甜点4
C++ 11新特性之语法甜点4
28 0
|
3月前
|
安全 C++ 容器
C++ 11新特性之语法甜点3
C++ 11新特性之语法甜点3
36 0
|
4月前
|
编译器 C++ 容器
C++语言的基本语法
想掌握一门编程语言,第一步就是需要熟悉基本的环境,然后就是最重要的语法知识。 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。 完整关键字
|
5月前
|
Java 编译器 程序员
C++中的语法知识虚继承和虚基类
**C++中的多继承可能导致命名冲突和数据冗余,尤其在菱形继承中。为解决这一问题,C++引入了虚继承(virtual inheritance),确保派生类只保留虚基类的一份实例,消除二义性。虚继承通过`virtual`关键字指定,允许明确访问特定路径上的成员,如`B::m_a`或`C::m_a`。这样,即使基类在继承链中多次出现,也只有一份成员副本,简化了内存布局并避免冲突。虚继承应在需要时提前在继承声明中指定,影响到从虚基类派生的所有后代类。**
|
5月前
|
编译器 C++ 开发者
C++一分钟之-属性(attributes)与属性语法
【7月更文挑战第3天】C++的属性(attributes)自C++11起允许附加编译器指令,如`[[nodiscard]]`和`[[maybe_unused]]`,影响优化和警告。注意属性放置、兼容性和适度使用,以确保代码清晰和可移植。示例展示了如何使用属性来提示编译器处理返回值和未使用变量,以及利用编译器扩展进行自动清理。属性是提升代码质量的工具,但应谨慎使用。
152 13
|
6月前
|
编译器 程序员 C++
C++一分钟之-属性(attributed)与属性语法
【6月更文挑战第28天】C++的属性为代码添加元数据,帮助编译器理解意图。C++11引入属性语法`[[attribute]]`,但支持取决于编译器。常见属性如`nodiscard`提示检查返回值,`maybe_unused`防止未使用警告。问题包括兼容性、过度依赖和误用。使用属性时需谨慎,确保团队共识,适时更新以适应C++新特性。通过示例展示了`nodiscard`和`likely/unlikely`的用法,强调正确使用属性能提升代码质量和性能。
90 13
|
6月前
|
编译器 C语言 C++