草庐IT

C++new的用法(涉及指针)

xvolare 2023-05-25 原文

首先,new和delete是成对使用的,new用于从堆内存申请一块空间,一般动态用于动态申请内存空间,即根据程序需要,申请一定长度的空间,而delete则是将new申请的空间释放。

new开辟的空间在堆上,而一般声明的变量存放在栈上。

一.new申请内存空间的三种基本格式

  • new 数据类型

  • new 数据类型(初始值)

  int  * p1=new int;

  int  *p2=new int(2); // *p2初始化值是2,这样直接在定义后面初始化是可以的
//也可以单独赋值  *p2=2;

 //如果不想使用指针,可以定义一个变量,在new之前用“*”表示new出来的内容
  int q = *new int;
  q = 1;
  cout << q << endl;

  int  *p3=new int[1000] //申请1000个单位内存空间

因为系统资源有限。

所以一般申请完后加一个条件进行判断(一般情况 不需要,申请特别大的内存时需要)

void Test()

{
 if(p3!=null)

{

   //程序代码
}

else

{

  //抛出异常,内存空间申请失败
}
 
}

用完以后记得删除

注意:只可以删除一次,不要对同一个指针多次使用delete

 delete p0;  //错误的,p0指针不是用new动态申请的
//下面三个是正确的写法

 delete p1;

 delete p2;

 delete[] p3; //注意此处不能用delete p3,因为在申请用了[],则在释放时要用delete[]
//注意   []中什么也不写

}

二.使用new来创建动态数组

int main()
{
using namespace std;
double* p3=new double[3];
p3[0]=0.2;//把指针当做数组名去使用即可,C++将数组名解释为数组第一个元素的地址
p3[1]=0.5;
p3[2]=0.8;
p3=p3+1;//对于数组名来说,是一个常量,不可以进行加减运算,但对于指针来说是个变量,于是可以。

//注意,因为上述操作使得p3指向了数组的第二个元素的地址,而在接下来需要删除时应该从首地址删除,所以需要-1操作(或者提前用一个指针标记好首地址以便后续删除操作)

p3=p3-1;
delete []p3;
return 0;

}

小插曲:

在对于两个指针指向字符串,需要复制时,应该使用strcpy函数

常常用于字符串char数组的初始化

strcpy(ps,animal);//将animal指向的字符串内容粘贴至ps所指字符串(需要提前确保内存空间足够)

strncpy函数,此函数会接受第三个参数,即复制的字符数

strncpy(ps,animal,19);

注意,这里我们假定ps数组长度为20,animal数组长度大于20,由于后者长度超过前者,若不加限制strncpy函数不会在最后一位加入'\0',因此,需要设置长度为19

ps[19]='\0';//手动补全空字符

警告:应该使用strcpy()或strncpy()而不是赋值运算符你来将字符串复制给数组

//strcpy
strcpy(p,"Hello");
cout<<*p<<endl; //只是输出p指向的字符串的第一个字符!
cout<<p<<endl; //输出p指向的字符串!
delete[] p;

    • 用new来开辟数组空间

一维: int *a = new int[100];//开辟一个大小为100的整型数组空间

二维: int **a = new int[5][6]

三维及其以上:依此类推.

一般用法: new 类型 [初值]

若数组大小是不确定的,可以如下操作

#include <iostream>
using namespace std;

int main()
{
    int size;
    cout << "Enter the size of the array: ";
    cin >> size;
    int *p = new int[size];
    // Use the array
    delete[] p;
    return 0;
}

典例应用

#include<iostream>
#include<cstring>
using namespace std;
char* getname();
int main()
{
char*name;
name=getname();
cout<<name<<"at"<<(int*)name<<"\n";
delete[]name;
name=getname();
cout<<name<<"at"<<(int*)name<<"\n";
delete[]name;
return 0;
}
char* getname()
{
char temp[80];
cout<<"Enter last name";
cin>>temp;
char* pn=new char[strlen(temp)+1];
strcpy(pn,temp);
return pn;

}
注意:

在使用动态数组时,你需要自己确保数组大小是合法的,并需要自己确保动态分配的内存能够被释放。

为了避免内存泄露,您应该在异常发生时删除动态分配的内存。

同时,一个常见的误区是:

sizeof 函数在 C++ 中用于获取一个变量或类型的大小,但它不能用来获取动态数组的长度。因为动态数组的大小是在运行时分配的,而 sizeof 是在编译时进行的。

如果要获取动态数组的长度,可以在创建数组时顺便记录下来,或者在调用 new 时传入一个变量来记录数组大小。

如:

int size = 10;
int *p = new int[size];
// do something with the array
cout << "The size of the array is: " << size << endl;


//or


int size;
cout << "Enter the size of the array: ";
cin >> size;
int *p = new int[size];
// do something with the array
cout << "The size of the array is: " << size << endl;
    • 还有个方法就是使用STL中vector,因为vector封装了new和delete,它本身维护了大小,我们可以直接使用 vectorName.size()来获取。

  • STL 中的 vector 是一种动态数组,它提供了与动态数组类似的功能,但是还提供了一些额外的特性,如随着元素数量增加而自动增长数组的大小。

举个例子,如果你想创建一个 int 类型的 vector,可以这样写:

#include <vector>
using namespace std;

int main()
{
    vector<int> v;
    // Use the vector
    cout<<"The size of vector is: "<<v.size()<<endl;
    return 0;
}

vector 内部维护了元素的个数,而不必手动记录。

当需要向 vector 中添加元素时,可以使用 push_back() 函数:

v.push_back(1);
v.push_back(2);

这样就可以在运行时获取动态数组的大小,而不必使用 sizeof 函数。

vector 比动态数组更安全,因为它维护了大小信息,而且自动释放内存,避免了内存泄露。

需要注意的是,vector 在空间不够时会自动重新分配内存,这意味着指向 vector 内存块的指针可能会发生改变,因此不能将 vector 的指针存储在指针数组中。

三.用new来创建动态结构

基本格式:

inflatable* ps=new inflatable;

注意:由于用这种方式创建的结构没有名称因此无法使用"."来获取成员函数

因此我们需要使用"->"运算符

如:

ps->price;//被指向的结构的price成员

简单来讲:如果使用的是结构名。就用"."

如果是指针,就用“->”

(记得delete)

To be continued......

有关C++new的用法(涉及指针)的更多相关文章

  1. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  2. ruby - 在 Ruby 中,为什么 Array.new(size, object) 创建一个由对同一对象的多个引用组成的数组? - 2

    如thisanswer中所述,Array.new(size,object)创建一个数组,其中size引用相同的object。hash=Hash.newa=Array.new(2,hash)a[0]['cat']='feline'a#=>[{"cat"=>"feline"},{"cat"=>"feline"}]a[1]['cat']='Felix'a#=>[{"cat"=>"Felix"},{"cat"=>"Felix"}]为什么Ruby会这样做,而不是对object进行dup或clone? 最佳答案 因为那是thedocumenta

  3. Ruby:行 "m = Hash.new {|h,k| h[k] = []}"完成了什么而 "Hash.new"没有完成? - 2

    一边学习thisRailscast我从Rack中看到了以下源代码:defself.middleware@middleware||=beginm=Hash.new{|h,k|h[k]=[]}m["deployment"].concat[[Rack::ContentLength],[Rack::Chunked],logging_middleware]m["development"].concatm["deployment"]+[[Rack::ShowExceptions],[Rack::Lint]]mendend我的问题是关于第三行。什么是传递block{|h,k|h[k]=[]}到Has

  4. ruby - 使用 Class.new 时访问外部范围 - 2

    是否有可能以某种方式访问​​Class.new范围内的a?a=5Class.new{defb;aend}.new.b#NameError:undefinedlocalvariableormethod`a'for#:0x007fa8b15e9af0>#:in`b' 最佳答案 即使@MarekLipka的回答是正确的——改变变量范围总是有风险的。这是可行的,因为每个block都带有创建它的上下文,因此您的局部变量a突然变得不那么局部了——它变成了一个“隐藏的”全局变量:a=5object=Class.new{define_method(

  5. ruby-on-rails - 在 Ruby 或 Rails 中,hash.merge({ :order => 'asc' }) can return a new hash with a new key. 什么可以返回带有已删除键的新散列? - 2

    在Ruby(或Rails)中,我们可以做到new_params=params.merge({:order=>'asc'})现在new_params是一个带有添加键:order的散列。但是是否有一行可以返回带有已删除key的散列?线路new_params=params.delete(:order)不会工作,因为delete方法返回值,仅此而已。我们必须分3步完成吗?tmp_params=paramstmp_params.delete(:order)returntmp_params有没有更好的方法?因为我想做一个new_params=(params[:order].blank?||para

  6. ruby 变量作为同一对象(指针?) - 2

    >>a=5=>5>>b=a=>5>>b=4=>4>>a=>5如何将“b”设置为实际的“a”,以便在示例中,变量a也将变为4。谢谢。 最佳答案 classRefdefinitializeval@val=valendattr_accessor:valdefto_s@val.to_sendenda=Ref.new(4)b=aputsa#=>4putsb#=>4a.val=5putsa#=>5putsb#=>5当您执行b=a时,b指向与a相同的对象(它们具有相同的object_id).当你执行a=some_other_thing时,a将指向

  7. ruby - 有人可以解释一下在 Ruby 中注入(inject)的真实、通俗易懂的用法吗? - 2

    我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有

  8. ruby-on-rails - 设计中的 ArgumentError::RegistrationsController#new 错误的参数数量(2 代表 0..1) - 2

    我在关注RyanbatesRailsCast的devise和omniauth(第235集-devise-and-omniauth-revised)。当我尝试使用Twitter登录时,标题中不断出现错误。defself.new_with_session(params,session)ifsession["devise.user_attributes"]new(session["devise.user_attributes"],without_protection:true)do|user|user.attributes=paramsuser.valid?end完整跟踪:C:/Ruby20

  9. ruby-on-rails - 从 ActiveAdmin has_many 表单助手中删除 "Add new"按钮 - 2

    我在事件管理员编辑页面中有嵌套资源,但我只想允许管理员编辑现有资源的内容,而不是添加新的嵌套资源。我的代码看起来像这样:formdo|f|f.inputsdof.input:authorf.input:contentf.has_many:commentsdo|comment_form|comment_form.input:contentcomment_form.input:_destroy,as::boolean,required:false,label:'Remove'endendf.actionsend但它在输入下添加了“添加新评论”按钮。我怎样才能禁用它,并只为主窗体保留f.ac

  10. ruby - 什么是 "Class.new"? - 2

    我不明白下面这段代码中的Sheep=Class.new部分。moduleFenceSheep=Class.newdodefspeak"Bah."endendenddefcall_sheepFence::Sheep.new.speakend它到底在做什么? 最佳答案 根据文档,Class.newCreatesanewanonymous(unnamed)classwiththegivensuperclass(orObjectifnoparameterisgiven).此外,Youcangiveaclassanamebyassigning

随机推荐