c++学习day2
本文最后更新于 36 天前,其中的信息可能已经有所发展或是发生改变。

开发环境

ubuntu下的g++编译器即可,随着gcc一起安装的

g++ (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

编译指令

g++ test.cpp -o test

string类型

在c语言中,是没有string这个类型的。想要表达字符串必须借助字符数组或者字符指针,极其不便。c++中原生支持string类型且自带方便的API调用接口。

例如:

int main() {
  // 定义string类型并进行拷贝初始化
  string str1 = "hello world";
  cout << "str1 : " << str1 << endl;

  // 构造函数初始化
  //以下都是重载函数,c++的特性,允许同名但参数或返回值不同的函数存在
  //   string();
  //   string( size_type length, char ch );
  //   string( const char *str );
  //   string( const char *str, size_type length );
  //   string( string &str, size_type index, size_type length );
  //   string( input_iterator start, input_iterator end );

  string str2("hello");
  cout << "str2 : " << str2 << endl;

  //部分API接口示例

  //赋值api assign
  string str3;
  str3.assign("this is str3");
  cout << "str3 : " << str3 << endl;

  //拼接api append
  string str4 = str3 + str2;
  cout << "str4 : "<<str4<<endl;

  //c_str 返回指向字符串的指针
  const char* str5 = str3.c_str();
  cout << "str5 : "<<str5<<endl;

  //迭代器循环遍历
  for (auto it = str4.begin(); it != str4.end(); ++it) {
        std::cout << *it << " "; // 用 * 访问当前位置的字符
    }
    std::cout << std::endl; 

    //capacity()函数返回在重新申请更多的空间前字符串可以容纳的字符数
    size_t strlen = str4.capacity();
    cout << "str4 capacity: " << strlen << endl;
  return 0;
}

引用

引用,就是给一个已经存在的变量取了一个“外号/别名”。

1. 现实生活中的比喻

  • 指针(Pointer):像一张写着房间号的纸条
    • 纸条上写着“302 房间”。纸条本身占用空间,纸条里的地址可以擦掉重写(指向别的房间),纸条也可能是空的(nullptr)。
  • 引用(Reference):像人的“外号”。
    • 比如“罗翔”的外号叫“张三”。
    • “罗翔”和“张三”指的是同一个实体。给“张三”一拳,“罗翔”脸上也会肿;给“张三”发 100 块红包,“罗翔”的钱包就会变鼓。

2. 代码怎么写?

在 C++ 中,在类型后面加个 & 就代表定义一个引用:

C++

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int& ref = a; // ref 是 a 的引用(外号)

    cout << "a = " << a << endl;     // 输出 10
    cout << "ref = " << ref << endl; // 输出 10

    ref = 20; // 通过外号修改值
    cout << "a = " << a << endl;     // a 也变成了 20!

    // 它们的内存地址一模一样!
    cout << &a << " == " << &ref << endl; 
}

注意:你在使用 ref 的时候,完全不需要像指针那样加 \* 解引用,把它当成普通变量直接用就行了!

3. 引用的“三大死铁律”(比指针省心的地方)

正是因为以下三条规则,引用用起来比指针安全得多

规则指针(int*)引用(int&)
1. 必须初始化可以不初始化(悬空指针,危险)必须在定义时绑定初始值! int& r; ❌ 编译报错
2. 从一而终随时可以指向其他变量(p = &b一旦绑定,终生不能更改指向!
3. 是否允许为空可以是 nullptr(使用前需要判断 if(p)绝不允许为空,必定指向某个真实存在的变量

💡 “从一而终”的小陷阱

如果你写 ref = b;这不是让 ref 转去引用 b,而是把 b 的值赋值ref 所引用的原变量 a

4. 为什么要发明引用?(C++ 创始人的用心)

在 C 语言时代,我们要写一个交换两个数的函数,必须传指针:

// C 语言方式:传指针
void swap(int* x, int* y) {
    int temp = *x; // 必须写一堆 *
    *x = *y;
    *y = temp;
}

int main() {
    int a = 1, b = 2;
    swap(&a, &b); // 调用时必须手动取地址 &
}

这样写语法非常繁琐,满屏幕都是 *&

C++ 引入引用后,代码变得无比优雅:

// C++ 方式:传引用
void swap(int& x, int& y) { // x 是 a 的别名,y 是 b 的别名
    int temp = x; // 像普通变量一样直接写!
    x = y;
    y = temp;
}

int main() {
    int a = 1, b = 2;
    swap(a, b); // 直接传 a 和 b,干净利落!
}

5. 底层真相:引用到底是个啥?

引用在 C++ 编译器底层的实现,本质上就是一个“被限制了功能的常指针(Type\* const)”

你写代码:

int& ref = a;
ref = 20;

编译器在后台为你做的事:

int* const ref = &a; // 自动帮你取地址,且指针本身不能修改指向
*ref = 20;            // 自动帮你加 * 访问内容

看明白了吧?引用其实是编译器提供的一种“语法糖”。它把指针繁琐的取地址(&)、解引用(*)、判空(nullptr)全都在后台自动化了,把方便和安全留给了程序员

6. 最常用的高级写法:const 引用

我们在写函数参数传递对象(比如 string 或自定义大类)时,最推荐的写法就是:const 类型&

// 既避免了拷贝大对象的内存消耗(高效),又防止函数内部不小心修改了原数据(安全)
void printMessage(const std::string& str) {
    // str.append("!"); // ❌ 编译报错!const 保护了原数据不被改动
    cout << str << endl;
}

总结

  • 指针:是一个独立的变量,里面存的是别人的地址,可以随时换指向,可以为空。(灵活但危险)
  • 引用:是别人的一个别名,与原变量同生共死,绑定后不可变,不能为空。(安全且书写简洁)

以后看到 int&,就在脑子里替换成“a 的外号”五个字,你就彻底通透了!

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇