没错我是langyo= =
怎么喂龙请去末地看申诉…
最近,我那个压缩算法就要出炉了,但在写C++版的算法时遇到了问题,问题出在动态内存分配上。
众所周知,要声明一个静态数组,其初始化下标必须是一个常量表达式。动态数组则比较有趣了,它需要你给个指针,然后new,动态开辟空间,用完后还得delete。
现在的问题是,我的压缩算法需要能够动态调整的内存空间,但理论来讲数组下限如果用变量会满屏Error红灿灿。如何才能以new申请出我动态指定量的内存?
别急着回复,我还没讲完。
我使劲查了资料,发现其实大家都是可以这么玩的,以变量为下限来new。不过,我看见的都是诸如char p*=new bytes[i];这种玩意。所以,其它数据类型不行,但char可以喽?如果不行,那GCC又是怎么做的呢?怎么才能做到用new动态申请内存?
最后,可能有人要我用malloc()和free(),也可能有人要我改用文件流替代数组,也可能有人建议我用链表、堆或向量…但我希望能用new,这个面向对象的产物,而不是一堆库,那太依赖系统了(不用反驳,库确实有一定依赖性,各系统GCC的实现不一样)。
感谢你能抽出时间听我扯皮,也希望你能给我建设性的回复。
怎么喂龙请去末地看申诉…
最近,我那个压缩算法就要出炉了,但在写C++版的算法时遇到了问题,问题出在动态内存分配上。
众所周知,要声明一个静态数组,其初始化下标必须是一个常量表达式。动态数组则比较有趣了,它需要你给个指针,然后new,动态开辟空间,用完后还得delete。
现在的问题是,我的压缩算法需要能够动态调整的内存空间,但理论来讲数组下限如果用变量会满屏Error红灿灿。如何才能以new申请出我动态指定量的内存?
别急着回复,我还没讲完。
我使劲查了资料,发现其实大家都是可以这么玩的,以变量为下限来new。不过,我看见的都是诸如char p*=new bytes[i];这种玩意。所以,其它数据类型不行,但char可以喽?如果不行,那GCC又是怎么做的呢?怎么才能做到用new动态申请内存?
最后,可能有人要我用malloc()和free(),也可能有人要我改用文件流替代数组,也可能有人建议我用链表、堆或向量…但我希望能用new,这个面向对象的产物,而不是一堆库,那太依赖系统了(不用反驳,库确实有一定依赖性,各系统GCC的实现不一样)。
感谢你能抽出时间听我扯皮,也希望你能给我建设性的回复。
本帖最后由 ustc_zzzz 于 2017-4-7 02:06 编辑
希望不要出现v4
楼主感兴趣的话可以看看C++程序的内存模型。
通常而言,一个程序在运行的时候分为四个区:
如果是诸如下面这样的类型声明时分配内存:
复制代码那么相应的内存属于静态内存会被分配到栈区。
如果是像楼主提到的那样的使用new申请内存:
复制代码那么相应的内存属于动态内存会被分配到堆区。
不过楼主似乎提到了变长数组?就像这样:
复制代码这种情况下,程序会按照给定的值自动在栈上分配相应长度的数组。
不过,楼主你问的这玩意,真的和MC有关么。。。
楼主感兴趣的话可以看看C++程序的内存模型。
通常而言,一个程序在运行的时候分为四个区:
- 常量区,用于存放常量数据,包括字符串等
- 数据区,用于存放全局变量等静态数据
- 栈区,用于管理静态分配的内存,包括函数参数等
- 堆区,用来管理动态分配的内存
如果是诸如下面这样的类型声明时分配内存:
- char c[450] = {0};
如果是像楼主提到的那样的使用new申请内存:
- char *c = new char[450];
不过楼主似乎提到了变长数组?就像这样:
- #include <cstdlib>
- int i = std::rand() & 0xff;
- char c[i];
不过,楼主你问的这玩意,真的和MC有关么。。。
本帖最后由 langyo_v3 于 2017-4-7 07:06 编辑
变长数组的格式究竟是怎样的?我总是搞混
(跟MC有那么一丁点关系,因为我之前用命令方块实现了变长数组OOC)
(我也不希望需要再注册,但有人抢注咋办XD)
ustc_zzzz 发表于 2017-4-7 01:55
希望不要出现v4
楼主感兴趣的话可以看看C++程序的内存模型。
变长数组的格式究竟是怎样的?我总是搞混
(跟MC有那么一丁点关系,因为我之前用命令方块实现了变长数组OOC)
(我也不希望需要再注册,但有人抢注咋办XD)
讲真,我没听懂你在描述什么,不过从你的描述知道你是一个大新手,首先
第一个问题,new/delete malloc/free 这个你就没搞懂什么时候该用哪个, new 他内部除了调用malloc外还调了构造函数 而malloc就只是申请内存。所以如果你单单只是存储一些数据完全可以用malloc, new也可以随你选择没什么区别反正我boss要求我写c++代码不管做什么都用new。
第二个问题 其实你没必要过多关注于数据类型,如果你只是想存储,那么你只需要知道你需要多少内存。比如我要申请12个字节内存 void*p = new char[12]; 或者 void *p = new int[3]; 当然语法需要强转,这里我只是大概写一下。得到12个字节的p你可以往里面写任意的东西 比如写个对象进去写什么都可以,C++不是类型安全的 可以强转 取决于你想写什么进去
第一个问题,new/delete malloc/free 这个你就没搞懂什么时候该用哪个, new 他内部除了调用malloc外还调了构造函数 而malloc就只是申请内存。所以如果你单单只是存储一些数据完全可以用malloc, new也可以随你选择没什么区别反正我boss要求我写c++代码不管做什么都用new。
第二个问题 其实你没必要过多关注于数据类型,如果你只是想存储,那么你只需要知道你需要多少内存。比如我要申请12个字节内存 void*p = new char[12]; 或者 void *p = new int[3]; 当然语法需要强转,这里我只是大概写一下。得到12个字节的p你可以往里面写任意的东西 比如写个对象进去写什么都可以,C++不是类型安全的 可以强转 取决于你想写什么进去
qqabxiaojing 发表于 2017-4-7 10:12
讲真,我没听懂你在描述什么,不过从你的描述知道你是一个大新手,首先
第一个问题,new/delete malloc/free ...
我主要还是用java比较熟练,c++只不过是用在算法考试的工具罢了
其实malloc已经够用了,毕竟new更应当用在面向对象,它还能因为class的特性而支持构造和析构
问题我已经自行解决了
你讲的话非常不清楚,但是我可以明确告诉你几点
1.不管是什么时候new都是c++最好选择
2.最好不要自己动手操作指针,尤其是在c++中,可以考虑STL里提供的泛型类(STL是c++标准库的一部分)
3.如果非要操作指针,切记销毁数组时用delete[]而不是delete
4.显然你没有搞懂怎么使用new。。。那你最好参见第二条
5.你在网上收集的资料明显略有偏颇,但更多是你自己的问题,参见第四条
6.不要妄图使用可变长度的数组,那会把问题变复杂
如果你想要更多了解c++,尤其是对上面建议不清楚的,或者想要我教你怎么解决你的问题
可以私信我,这里因为篇幅原因就不详细说了。
我也可以收个c++学徒什么的,反正学了这么久c++也是闲的慌
1.不管是什么时候new都是c++最好选择
2.最好不要自己动手操作指针,尤其是在c++中,可以考虑STL里提供的泛型类(STL是c++标准库的一部分)
3.如果非要操作指针,切记销毁数组时用delete[]而不是delete
4.显然你没有搞懂怎么使用new。。。那你最好参见第二条
5.你在网上收集的资料明显略有偏颇,但更多是你自己的问题,参见第四条
6.不要妄图使用可变长度的数组,那会把问题变复杂
如果你想要更多了解c++,尤其是对上面建议不清楚的,或者想要我教你怎么解决你的问题
可以私信我,这里因为篇幅原因就不详细说了。
我也可以收个c++学徒什么的,反正学了这么久c++也是闲的慌
姚氏帅哥 发表于 2017-4-7 12:40
你讲的话非常不清楚,但是我可以明确告诉你几点
1.不管是什么时候new都是c++最好选择
2.最好不要自己动手操 ...
我需要动态数组的原因,是为了动态实现分区块
new的基础格式,我只有这个疑惑,现在已经完美解决了(刚刚用学校电脑测试了,编译通过)
至于你觉得我对new运算符理解得不够透彻…我更偏向java,但java里到处都是new,再怎么不会也得被这种环境整会了啊…
其实,写算法时都不需要这动态数组,因为人家题目会给数据范围…
c++学徒?…算了算了= =你倒不如跟我说说怎么在NOI突破到全国竞赛…
langyo_v3 发表于 2017-4-7 13:27
我需要动态数组的原因,是为了动态实现分区块
new的基础格式,我只有这个疑惑,现在已经完美解决了(刚刚用学 ...
C++的new和java的new差别可不止一点,如果完全照搬java的思维可是会出事的。
顺便orz 切NOI的dalao
WA自动机 发表于 2017-4-8 12:29
C++的new和java的new差别可不止一点,如果完全照搬java的思维可是会出事的。
顺便orz 切NOI的dalao ...
C++的类比java的放荡,多继承什么的,太可恶了XD
而且new了必须自己delete,确实和java不同
但照搬,就算想也做不到,因为C++可以直接操作指针,java则围绕类做了一堆事情
至于NOI呐,说实话,原理不难,但编的时候难,因为要考虑最短时间复杂度XD
langyo_v3 发表于 2017-4-8 13:08
C++的类比java的放荡,多继承什么的,太可恶了XD
而且new了必须自己delete,确实和java不同
如果是java的话可以用集合然后集合←→数组互转即可
但是C++有集合这个功能么?我不是很清楚,因为学C++同样是为了NOIP
另:NOIP取消对JAVA的支持真是太可恶了
另2:你是哪个省区的XD运气好说不定我们会碰面呢
Smokey_Days 发表于 2017-4-16 17:37
如果是java的话可以用集合然后集合←→数组互转即可
但是C++有集合这个功能么?我不是很清楚,因为学C++ ...
江苏的XD
所以今年11月见?XD
java比起C++,好用太多了,只是性能有所欠缺罢了
langyo_v3 发表于 2017-4-8 13:08
C++的类比java的放荡,多继承什么的,太可恶了XD
而且new了必须自己delete,确实和java不同
你不用多继承不就不可恶了么
new的确需要自己delete
但是c++程序员会利用构造函数new利用析构函数delete
还可以加个计数器什么的灵活度速度都比java高
加上泛型几乎和Java的差不多了
本帖最后由 姚氏帅哥 于 2017-4-16 18:23 编辑
c++的确有合集。。。我不可能详细的说
但是最常用,最好用的是vector
大概像这样
std::vector<int> v = {1,2,3};
v.push_back(4);//在末尾插入4
for(int n : v)std::cout<<n;//它会输出1234
当然还有map
std::map<std::string,int> m;
m["hello"]=4;//方括号里面是键,等号右面是值
Smokey_Days 发表于 2017-4-16 17:37
如果是java的话可以用集合然后集合←→数组互转即可
但是C++有集合这个功能么?我不是很清楚,因为学C++ ...
c++的确有合集。。。我不可能详细的说
但是最常用,最好用的是vector
大概像这样
std::vector<int> v = {1,2,3};
v.push_back(4);//在末尾插入4
for(int n : v)std::cout<<n;//它会输出1234
当然还有map
std::map<std::string,int> m;
m["hello"]=4;//方括号里面是键,等号右面是值
姚氏帅哥 发表于 2017-4-16 18:10
你不用多继承不就不可恶了么
new的确需要自己delete
但是c++程序员会利用构造函数new利用析构函数delete
那个…C++那个不叫泛型…叫虚函数…
langyo_v3 发表于 2017-4-16 18:20
那个…C++那个不叫泛型…叫虚函数…
你确定?你了解c++?c++用模板实现泛型好吗
langyo_v3 发表于 2017-4-16 18:20
那个…C++那个不叫泛型…叫虚函数…
你之前问关于c++动态内存的时候我就回答过你
看得出来你非常迫切想要参加noip(其实我也想)
但是,就目前而言,你用Java的方式理解c++
相当的不好,最后你的脑袋会拧成麻花
你对我进行指正,说泛型是虚函数
然而这并不是Java中的伪泛型,不是靠的是语法糖
不是靠把T换成Object等做法构成的“多态泛型”
c++泛型与继承、多态、虚函数没有半毛钱关系
所以你看到了c++泛型与Java的泛型是不能相提并论的
还有,需要指出的是,Java除了静态方法之外
其他方法都是虚函数,而c++不同需要手动指定
姚氏帅哥 发表于 2017-4-16 21:41
你之前问关于c++动态内存的时候我就回答过你
看得出来你非常迫切想要参加noip(其实我也想)
但是,就目前 ...
额,NOI早着呢,隔一暑假急啥
java的泛型是语法糖,编译时自动匹配数据类型,C++也是一样的么?
langyo_v3 发表于 2017-4-16 21:45
额,NOI早着呢,隔一暑假急啥
java的泛型是语法糖,编译时自动匹配数据类型,C++也是一样的么? ...
Java泛型最重要的一个环节就是“类型擦除”
把所有涉及泛型的地方换成Object
在加上一些强制类型转换,所以Java泛型不支持基本类型
因为他们不能实现上述内容
在这里不具体讲,你可以在论坛里找一下Java泛型研究
c++不同,实际上c++的泛型是通过“模板”(template)实现的
template是一个巨坑,一般教程只教泛型这部分(甚至泛型都只讲这一部分)
这里不想详细的说,其实你可以私信我的。。。那样交流顺畅些
参考STL库,比如动态数组去看看vector底层的实现,也算是比较权威的
该运算符将返回一个指针,详情还请你去百度上查找资料。链表是依靠new和delete实现的。malloc()类似new,free()类似delete。
zcm2005 发表于 2017-5-8 20:54
该运算符将返回一个指针,详情还请你去百度上查找资料。链表是依靠new和delete实现的。malloc()类似new,fr ...
链表同样可以通过malloc()与free()实现,只不过不是很方便罢了
new/delete与malloc()/free()最明显的不同,是new/delete在初始化class时自动帮你执行构造和析构,但malloc()/free()得你自己费事手动执行
langyo_v3 发表于 2017-5-8 21:37
链表同样可以通过malloc()与free()实现,只不过不是很方便罢了
new/delete与malloc()/free()最明显的不同 ...
本质上你说得对
从概念上,注意我说的是概念,就是如何理解它
你应该把malloc想成分配内存,干啥你随便
free释放内存,之后啥都不干。。。
new创建对象,当然会调用构造函数
delete是销毁对象,自然析构函数少不了
注意:基本类型构造自动初始化为0
基本类型没有析构函数,即销毁时啥都不做
并且基本类型只在特殊情况调用它的构造函数
比如new,创建数组int a[20],静态变量等等
姚氏帅哥 发表于 2017-5-8 23:17
本质上你说得对
从概念上,注意我说的是概念,就是如何理解它
你应该把malloc想成分配内存,干啥你随便
基本类型的构造函数是怎样的?
(请以知乎环境回答XD)
langyo_v3 发表于 2017-5-8 23:10
基本类型的构造函数是怎样的?
(请以知乎环境回答XD)
知乎没用过,所以啥是知乎环境啊
其实就是自动初始化为0而已(*this=0),而且这个构造还不是像其他类那样,自动调用
而是必须我前面提到的特殊情况,或者也可以显式调用
如int() double(12) bool(ptr)
等等,具体的今天太晚了,之后再说XD
(说是构造函数,其实是什么你应该很清楚)
这么说吧 malloc/free是函数,new/delete是操作符
顶个热水袋 发表于 2017-5-11 07:48
这么说吧 malloc/free是函数,new/delete是操作符
同志你听说过operator new 和 operator delete 吗
没错,你可以理解为操作符,但是本质上是函数
(上述函数声明于<new>当中)
虽然本质上是函数,操作符这种说法还是最优的
尤其是你重载他们的时候
不过你不说我还真没想起来这件事
邀请围观:@langyo_v3
顶个热水袋 发表于 2017-5-11 07:48
这么说吧 malloc/free是函数,new/delete是操作符
再准确点,
malloc/free是库函数
new/delete是实实在在的关键字
姚氏帅哥 发表于 2017-5-11 08:01
同志你听说过operator new 和 operator delete 吗
没错,你可以理解为操作符,但是本质上是函数
(上述函 ...
new/delete准确来说是关键字,operator new/opreator delete是标准库函数。
operator new can be called explicitly as a regular function, but in C++, new is an operator with a very specific behavior: An expression with the new operator, first calls function operator new (i.e., this function) with the size of its type specifier as first argument, and if this is successful, it then automatically initializes or constructs the object (if needed). Finally, the expression evaluates as a pointer to the appropriate type.
看下这段,来自www.cplusplus.com
顶个热水袋 发表于 2017-5-30 20:28
new/delete准确来说是关键字,operator new/opreator delete是标准库函数。
operator new can be called ...
你的意思是说new和delete可以被重载?
一口老血喷…
langyo_v3 发表于 2017-5-30 21:24
你的意思是说new和delete可以被重载?
一口老血喷…
当然可以。。。小伙子,c++的坑有多深?谁也说不清
顶个热水袋 发表于 2017-5-30 20:28
new/delete准确来说是关键字,operator new/opreator delete是标准库函数。
operator new can be called ...
这个我倒是知道。。。,但是你这又把话题扯回来了。。
langyo_v3 发表于 2017-5-30 21:24
你的意思是说new和delete可以被重载?
一口老血喷…
new/delete确实是不允许重载的,我的意思不是可以重载,只是说new/delete和operator new/opreator delete是两种东西,
- Type* p=new Type;
- //这个调用分3步
- //1.调用operator new函数,分配未类型化的内存,保存指定类型的对象
- //2.运行对应类型的构造函数,初始化对象
- //3.返回指向对象的指针
说到重载,其实可以在类中定义自己的new/delete成员/友元函数或者定义全局的函数,或者是new[]/delete[]函数,这个算是另一种意义的重载:
- void opreator new(void* p);
- void* operator new(size_t t);
- void operator new(size_t t,void* p);
- Type* p=new Type;
如果还是要使用标准库给好的:
- Type* p=::new Type;
其实纠结这么多也没用,先实现功能比较重要。
顶个热水袋 发表于 2017-5-31 16:48
new/delete确实是不允许重载的,我的意思不是可以重载,只是说new/delete和operator new/opreator delete ...
@姚氏帅哥
new/delete很神奇,对吧
operation是个很有趣的东西
langyo_v3 发表于 2017-5-31 20:05
@姚氏帅哥
new/delete很神奇,对吧
他讲的很对。。。重载这两个运算符本质上只是对分配的内存做事,不是自定义如何分配内存
本帖最后由 Lne 于 2017-6-6 11:00 编辑
复制代码
或者
复制代码
- #include <vector>
或者
- #include <memory>//智能指针 想像java那样用new应该是用这玩意(但是不等同于垃圾回收)
(好吧忘记看时间了)
虽然vector是最常用的,但是c++标准库还包含了
list deque forward_list stack queue等容器。。。
以及一些较为特殊的像pair tuple initializer_list等容器
至于智能指针,我只有一个建议——别用auto_ptr!
@langyo_v3 ← 楼主
姚氏帅哥 发表于 2017-6-6 11:06
虽然vector是最常用的,但是c++标准库还包含了
list deque forward_list stack queue等容器。。。
以及一 ...
这帖沉不了,因为这帖讨论的是大家都津津乐道的语法…
langyo_v3 发表于 2017-6-6 13:04
这帖沉不了,因为这帖讨论的是大家都津津乐道的语法…
为什么要津津乐道
顶个热水袋 发表于 2017-6-8 10:38
为什么要津津乐道
因为只有语法这部分最容易与别人拉开距离
langyo_v3 发表于 2017-6-8 13:14
因为只有语法这部分最容易与别人拉开距离
这样啊。。。
langyo_v3 发表于 2017-5-31 20:05
@姚氏帅哥
new/delete很神奇,对吧
我再来给你看个大♂宝♂贝
char *p = new[sizeof(T)]
new (p) T(1,2,3);
你猜猜是什么含义?
我看了下很早之前你和4z的对话
以及边长数组是C11的特性4z说的那个肯定不可能
而且c11不被广泛支持与使用,比c++11惨一万倍
非要数组边长就不断的new和delete就行了╭(╯3╰)╮
如果你对标准库怨气有加,你可以自己编写容器/智能指针
此外我还要说1.c++的容器从来都没有一个共同父类,所以Collection千万别来
二的一个是迭代器,他是c++容器必备的
三的一个就是泛型算法千万不要作为容器的成员
姚氏帅哥 发表于 2017-6-8 22:54
我再来给你看个大♂宝♂贝
char *p = new
new (p) T(1,2,3);
含义没看出来,但C11很惨是真的
顶个热水袋 发表于 2017-5-31 16:48
new/delete确实是不允许重载的,我的意思不是可以重载,只是说new/delete和operator new/opreator delete ...
@顶个热水袋
你说operator new 和 new 不是同一个东西
那我还可以说。operator+ 和 + 不是同一个东西呢//其实本来就不是
但是强行区分没有意义,毕竟运算符重载本来就是语法糖,本来就是为了方便
还有你说new分为3步
//这个调用分3步
//1.调用operator new函数,分配未类型化的内存,保存指定类型的对象
//2.运行对应类型的构造函数,初始化对象
//3.返回指向对象的指针
其实只有第一步,因为构造函数本身就与new无关。。。构造函数根本不是new调用的。。。
至于返回不是废话吗。。。
所以其实new就只用一步:调用operator new
@langyo_v3
姚氏帅哥 发表于 2017-6-9 12:37
@顶个热水袋
你说operator new 和 new 不是同一个东西
那我还可以说。operator+ 和 + 不是同一个东西呢/ ...
对于基本类型,只有一步。
- int* p=new int;
- 00E54C44 push 4
- 00E54C46 call operator new (0E51384h)
- 00E54C4B add esp,4
- struct Object{};
- Object* o=new Object;
- 00AD7EDD push 4
- 00AD7EDF call operator new (0AD1384h)
- 00AD7EE4 add esp,4
- 00AD7EE7 mov dword ptr [ebp-0E0h],eax
- 00AD7EED mov dword ptr [ebp-4],0
- 00AD7EF4 cmp dword ptr [ebp-0E0h],0
- 00AD7EFB je main+70h (0AD7F10h)
- 00AD7EFD mov ecx,dword ptr [ebp-0E0h]
- 00AD7F03 call Object::Object (0AD1433h) //在new的地址上调用构造函数
- 00AD7F08 mov dword ptr [ebp-0F4h],eax
- 00AD7F0E jmp main+7Ah (0AD7F1Ah)
- 00AD7F10 mov dword ptr [ebp-0F4h],0
- 00AD7F1A mov eax,dword ptr [ebp-0F4h]
- 00AD7F20 mov dword ptr [ebp-0ECh],eax
- 00AD7F26 mov dword ptr [ebp-4],0FFFFFFFFh
- 00AD7F2D mov ecx,dword ptr [ebp-0ECh]
- 00AD7F33 mov dword ptr [p],ecx
我前面说了,纠结这个没意义,这帖子本来就是楼主要实现一个东西,实现出来能跑为上。
你要继续纠结,那你是对的。我甘拜下风。
既然是搞算法竞赛为啥要考虑动态内存。。有多少上多少啊!
顶个热水袋 发表于 2017-6-9 14:40
对于基本类型,只有一步。复杂类型就是三步我区分开只是我觉得这样子让我理解起来容易,你要怎么理解是你 ...
不管是基本类型还是复杂类型,用的不都是operator new 和 new
而你前面说的是“new和operator new的区别”
不过把汇编翻出来也是挺厉害的。。。
Paindar 发表于 2017-6-9 16:15
既然是搞算法竞赛为啥要考虑动态内存。。有多少上多少啊!
我需要动态内存是因为一些变态的用途,它不是用来玩NOIP/NOI的
比如说实现动态链表,vector就是这么玩的
顶个热水袋 发表于 2017-6-9 14:40
对于基本类型,只有一步。复杂类型就是三步我区分开只是我觉得这样子让我理解起来容易,你要怎么理解是你 ...
能把你用的解析汇编的软件发给我吗?
langyo_v3 发表于 2017-6-9 19:25
我需要动态内存是因为一些变态的用途,它不是用来玩NOIP/NOI的
比如说实现动态链表,vector就是这么玩的 ...
荒谬!谁跟你说vector是链表的
vector明明是用数组实现的好吗
链表是list和forward_list
实现动态链表炒鸡简单的。。。(用Java会更简单
但是明明有标准库的为什么你要自己写呢....