(语法)内存地址和指针<一>

本文详细介绍了计算机内存的工作原理及不同数据类型在内存中的分配情况。同时深入探讨了指针的概念及其在程序中的应用,包括如何声明和使用指针。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    根据这段时间的学习深深感觉到应该要深入理解内存机制和指针的用法真的很重要,这是第一篇,也是目前对内存和指针的认识的总结。

    内存:就好像一个容器,可以装纳数据在里面,这个容器不是一整块的,它是分了很多很多的小格子,即内存中的位,每个格子装一个0或者1,而我们要放到容器中的数据实际上也是要将他分解成很多段再放进去的,就是将数据转换成二进制0和1再放进内存中。

    变量:在程序中声明一个变量后,则会根据所声明变量的类型在内存中开辟一个空间给这个变量使用,

各类数据类型的内存使用及取值范围:

   BOOL型为int型,一般认为占4个字节,取值TRUE/FALSE/ERROR。
sbyte型为有符号8位整数,占1个字节,取值范围在128~127之间。
bytet型为无符号16位整数,占2个字节,取值范围在0~255之间。
short型为有符号16位整数,占2个字节,取值范围在-32,768~32,767之间。
ushort型为无符号16位整数,占2个字节,取值范围在0~65,535之间。
int型为有符号32位整数,占4个字节,取值范围在-2,147,483,648~2,147,483,647之间。
uint型为无符号32位整数,占4个字节,取值范围在0~4,294,967,295之间。
long型为64位有符号整数,占8个字节,取值范围-9,223,372,036,854,775,808~9,223,372,036,854,775,807之间。
ulong型为64位无符号整数,占8个字节,取值范围在0~18,446,744,073,709,551,615之间。
float型为32位单精度实数,占4个字节,取值范围3.4E+10的负38次方~3.4E+10的38次方之间。
double型为64位实数,占8个字节,取值范围1.7E+10的负308次方~1.7E+10的正308次方。

需要注意的是每个字节占8位

    变量在内存中是无意义的,它只是代表了一些需要随时变化的在内存中的数据,为了方便编写代码,在程序编译前使用变量来代表这些内存空间。

    指针:指针也是一个变量,不过这个变量不是用来装数据的,它只是用来存储内存地址,并可以直接访问内存地址修改对应的数据。我们知道每个数据都需要声明一个变量来为它开辟内存空间存储起来,而变量即使那块空间的内存地址,比如声明一个变量a,int a=100;那么我们就可以使用int* p=&a将变量a的内存地址提取出来并把这个地址存储到指针变量p中去。指针变量也是一个变量,它也在内存中开辟一定的空间以供存储内存地址。这个空间很小,因为内存地址就是整数,如0x7fff9575c05f(以0X开头的表示后面的数字以16进制表示),就是一段16进制的数字表示。

内存地址用处很多,比如可以在函数调用中将一个内存地址作为实参传递给形参的指针,在被调用函数中就可以

利用这个指针直接对那一块内存进行调用。

指针的声明:数据类型* 指针变量名;如int* p;

指针的赋值: 左值(写操作):int* p=100;即将100传递到指针p指向的内存空间中去。

右值(读操作):int a; a=*p;即将指针p指向的内存空间中的数据传递给变量a。


<think>好的,我现在需要分析用户的问题,也就是关于C++中`unique_ptr<vector<int>> p (new vector<int>(5, 6));`这句的语法。用户之前已经问过关于`std::make_shared`的问题,现在转到了`unique_ptr`,可能是在学习智能指针的不同类型。 首先,我要确认用户是否了解智能指针的基本概念,比如`unique_ptr``shared_ptr`的区别。因为用户之前的问题是关于`shared_ptr`的,现在问的是`unique_ptr`,可能需要简要对比两者的不同,但重点还是解释当前的语法。 接下来,分解用户给出的代码。这句代码声明了个`unique_ptr`对象,指向个动态分配的`vector<int>`。构造函数的参数是`new vector<int>(5, 6)`。我需要解释各个部分的作用:`new`运算符分配内存并构造对象,`vector<int>(5, 6)`创建个包含5个元素,每个元素初始化为6的向量。然后,这个指针被传递给`unique_ptr`的构造函数,由`unique_ptr`管理所有权。 然后,我需要考虑用户可能的疑问点。比如,为什么使用`new`而不是`make_unique`?用户可能对C++11之后的`make_unique`函数不熟悉,或者代码示例使用的是旧的标准。需要指出C++14引入了`make_unique`,但这里直接使用`new`是显式的构造方式,可能在某些情况下需要,但通常推荐使用`make_unique`来避免内存泄漏的风险。 另外,用户可能会对模板参数`vector<int>`的位置感到困惑,即`unique_ptr<vector<int>>`的正确性。需要说明模板参数指定了指针指向的类型,这里正确,但可能需要指出在C++11中是否需要额外的空格,比如`>>`是否会被解析为右移运算符,不过在C++11之后编译器已经能够正确处理这种情况,不需要空格。 再者,需要解释`unique_ptr`的所有权特性,即独占所有权,不能复制只能移动,这与之前的`shared_ptr`不同。用户可能想知道为什么选择`unique_ptr`而不是`shared_ptr`,所以可能需要简要说明适用场景。 还需要检查是否有语法错误,比如是否遗漏了`std::`命名空间,或者是否正确的构造函数调用。用户给出的代码中,假设已经正确使用了`using namespace std;`或者前边有`std::`,但代码示例中可能没有显式写出,需要指出这点,或者提醒用户注意命名空间的问题。 另外,解释`new vector<int>(5,6)`的含义,即调用`vector`的构造函数,第个参数是元素数量,第二个是初始值。所以创建的vector有5个元素,每个都是6。 总结下来,回答的结构应该是先分解代码的各个部分,解释每个部分的作用,然后讨论可能的疑问点,比如为什么使用`new`而不是`make_unique`,所有权问题,以及语法细节,比如模板参数的正确性,最后给出示例代码说明用法注意事项。 可能还需要对比`make_shared``make_unique`的区别,说明在C++14中`make_unique`的存在,以及为什么推荐使用它。同时,指出使用`new`的潜在问题,比如异常安全,如果在构造`unique_ptr`之前`new`成功,但在构造过程中抛出异常,可能导致内存泄漏,而`make_unique`可以避免这种情况。 最后,确保回答清晰,分点说明,帮助用户理解每个部分,并给出示例最佳实践建议。</think>--- ### **代码解析:`unique_ptr<vector<int>> p (new vector<int>(5, 6));`** 这行代码使用 `std::unique_ptr` 智能指针管理个动态分配的 `std::vector<int>` 对象。以下是逐层分析: --- #### **1. 语法结构** ```cpp std::unique_ptr<std::vector<int>> p(new std::vector<int>(5, 6)); ``` - **`std::unique_ptr<std::vector<int>>`**: 声明个 `unique_ptr` 智能指针,模板参数指定它指向的类型为 `std::vector<int>`。 - **`p`**: 智能指针的变量名。 - **`new std::vector<int>(5, 6)`**: 动态分配个 `std::vector<int>` 对象,并调用其构造函数 `vector(size_type count, const T& value)`,创建个包含 5 个元素、每个元素初始化为 6 的向量。 --- #### **2. `unique_ptr` 的核心特性** - **独占所有权**: `unique_ptr` 对指向的对象拥有唯所有权,不可复制(禁用拷贝构造函数/赋值),但可以通过 `std::move` 转移所有权。 - **自动释放内存**: 当 `p` 离开作用域时,会自动调用 `delete` 释放其管理的 `vector<int>` 对象,无需手动 `delete`。 --- #### **3. 构造函数参数解析** `new std::vector<int>(5, 6)` 的具体行为: - **动态内存分配**:在堆(Heap)上分配内存,构造个 `std::vector<int>` 对象。 - **构造函数调用**: ```cpp vector<int>(5, 6); // 创建个包含 5 个元素的 vector,每个元素值为 6 ``` 等效于: ```cpp std::vector<int> vec {6, 6, 6, 6, 6}; ``` --- #### **4. 对比 `make_unique`(C++14 起支持)** C++14 引入了 `std::make_unique`,更推荐使用它来替代直接使用 `new`: ```cpp auto p = std::make_unique<std::vector<int>>(5, 6); ``` ##### **为什么推荐 `make_unique`?** 1. **异常安全**: 如果直接使用 `new`,在构造 `unique_ptr` 前可能发生异常,导致内存泄漏;`make_unique` 将分配内存构造智能指针合并为原子操作,避免此问题。 2. **代码简洁性**: 无需显式写出 `new` 模板类型,编译器自动推导。 3. **性能优化**: 与 `std::make_shared` 类似,`make_unique` 可能在某些情况下优化内存分配。 --- #### **5. 关键注意事项** - **禁止拷贝**: ```cpp std::unique_ptr<std::vector<int>> p2 = p; // 错误!unique_ptr 不可拷贝 std::unique_ptr<std::vector<int>> p3 = std::move(p); // 正确:转移所有权 ``` - **手动释放资源**: 可通过 `p.release()` 放弃所有权(返回裸指针,需手动管理),或 `p.reset()` 主动释放内存。 - **访问对象**: 通过 `p->` 操作符访问 `vector` 的成员: ```cpp p->push_back(7); // 向 vector 添加元素 std::cout << p->size(); // 输出 6(原5个元素+新增1个) ``` --- #### **6. 完整示例** ```cpp #include <memory> #include <vector> #include <iostream> int main() { // 使用 new 初始化 unique_ptr std::unique_ptr<std::vector<int>> p(new std::vector<int>(5, 6)); p->push_back(7); // 输出 vector 内容 for (int num : *p) { std::cout << num << " "; // 输出:6 6 6 6 6 7 } // p 离开作用域,自动释放内存 } ``` --- ### **总结** - **语法本质**:通过 `new` 动态分配内存,用 `unique_ptr` 管理其生命周期。 - **核心用途**:确保资源自动释放,避免内存泄漏。 - **最佳实践**:优先使用 `std::make_unique`(C++14 及以上)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值