【50分】动态申请指针数组 ptr = malloc(sizeof(char *) * n);这申请了多大的内存?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【50分】动态申请指针数组 ptr = malloc(sizeof(char *) * n);这申请了多大的内存?相关的知识,希望对你有一定的参考价值。

注意size of里面是char*而不是char,我知道一个char的长度是8字节,那一个char*的长度是多少了呢?

您好!和您一样,我也遇到过这样的问题。首先我要更正你的一个错误:char的长度应该是一个字节,char*是指向char类型的指针。至于ptr = malloc(sizeof(char *) * n)应该是用于ptr是一个指针数组的情况,char *专门用于指以'\0'为结束的字符串,这里用于动态给指针数组分配空间。sizeof()的大小取决于编译环境,ptr = malloc(sizeof(char *) * n)在32位编译环境下申请了4*n个字节。 参考技术A char是1个byte,8个bit,sizeof返回的是byte,所以sizeof(char)是1。而sizeof(char*)取决于编译环境,32位下是4,64位下是8。所有指针类型的sizeof都一样,即32位编译环境下sizeof(char*),sizeof(int*)等都是4。
所以 ptr = malloc(sizeof(char *) * n)在32位编译环境下申请了4*n个字节。追问

char*是什么东东啊?和char有什么区别?本人菜鸟一只。。。。

追答

char*是指向char类型的指针,字符变量,字符数组,字符串都可以用char*指向,例如char c; char* p = &c;

参考技术B 指针里装的是地址,所以
指针的长度当然是4个字节了(对32位程序而言)

另外,char的长度是1个字节,谁说是8个字节了,1字节=8位

shared_ptr和动态数组

std::shared_ptr智能指针是c++11一个相当重要的特性,可以极大地将开发者从资源申请/释放的繁重劳动中解放出来。

然而直到c++17前std::shared_ptr都有一个严重的限制,那就是它并不支持动态数组:

#include <memory>

std::shared_ptr<int[]> sp1(new int[10]()); // 错误,c++17前不能传递数组类型作为shared_ptr的模板参数
std::unique_ptr<int[]> up1(new int[10]()); // ok, unique_ptr对此做了特化

std::shared_ptr<int> sp2(new int[10]()); // 错误,可以编译,但会产生未定义行为,请不要这么做

sp1错误的原因很明显,然而sp2的就没有那么好找了,究其原因,是因为std::shared_ptr对非数组类型都使用delete p释放资源,显然这对于new int[10]来说是不对的,对它应该使用delete [] p

其实c++17前的解决方案并不复杂,我们可以借助std::default_delete,它用于提供对应类型的正确的delete操作:

std::shared_ptr<int> sp3(new int[10](), std::default_delete<int[]>());

现在我们提供了正确的delete操作,可以放心地使用了。

不过这么做的缺点也是很明显的:

  1. 我们想管理的值是int[]类型的,然而事实上传给模板参数的是int
  2. 需要显示提供delete functor
  3. 不能使用std::make_shared,无法保证异常安全
  4. c++17前shared_ptr未提供opreator[],所以当需要类似操作时不得不使用sp3.get()[index]的形式

事实上共享一片连续分配内存的需求是极为常见的,所以为了修正上述缺陷,c++17以及即将推出的c++2a对std::shared_ptr做了完善。

先说c++17的改进,shared_ptr增加了opreator[],并可以使用int[]类的数组类型做模板参数,所以sp3的定义可以简化了:

std::shared_ptr<int[]> sp3(new int[10]());

对于访问分配的空间,可以将sp3.get()[index]替换为sp3[index]。看个具体的例子:

#include <iostream>
#include <memory>

int main()
{
    std::shared_ptr<int[]> sp(new int[5]());
    for (int i = 0; i < 5; ++i) {
        sp[i] = (i+1) * (i+1);
    }

    for (int i = 0; i < 5; ++i) {
        std::cout << sp[i] << std::endl;
    }
}

我们分配一个有5个int元素的动态数组,然后分别赋值1-5的平方,然后输出:

g++ -Wall -std=c++17 test.cpp
./a.out

1
4
9
16
25

使用被极大得简化了,然而还是有点问题,那就是无法使用std::make_shared,而我们除非指定自己的delete functor,否则我们应该尽量使用std::make_shared

所以c++20对此做了改进:

auto up2 = std::make_unique<int[]>(10); // 从c++14开始,分配一个管理有10个int元素的动态数组的unique_ptr

// c++2a中你可以这样写,与上一句相似,只不过返回的是shared_ptr
auto sp3 = std::make_shared<int[]>(10);

在我的编译器上(GCC 8.2.1)还不能支持这一特性,所以很遗憾得不能提供演示了。

不过等c++2a(很可能就叫c++20)发布后std::shared_ptr就能安全而便捷地管理动态数组了。

以上是关于【50分】动态申请指针数组 ptr = malloc(sizeof(char *) * n);这申请了多大的内存?的主要内容,如果未能解决你的问题,请参考以下文章

在动态分配的数组上使用 auto_ptr 的正确方法是啥?

智能指针之 unique_ptr

指向动态声明的 cstrings 数组的指针

为啥free函数不在释放内存后,将指针置NULL,野指针有啥用

数据结构与算法之线性表(链式存储)

C++动态申请数组问题