Error[8]: Undefined offset: 669, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

new/delete 和malloc/free 的区别

共同点:

功能相同,new 和malloc 都是在堆区申请指定大小的内存空间,delete 和 free 都是释放指定的一块堆区内存空间(内部实现细节不同,不要混用)。


不同点:

new 和 delete 是 C++中新增的运算符,而malloc 和 free 是函数,所以运算符的执行效率比函数高(对于非对象数据)。


对于非对象数据,它们基本没有区别。


对于对象数据:

  1. 使用 new 运算符在堆区给对象申请空间后,还会调用对像的某个匹配的构造函数,而malloc 函数仅仅就是给对象申请堆区空间,并不会调用其构造函数。


  2. 使用 delete 运算符释放对象时,它首先会调用一次该对象的析构函数,然后再释放对象所占的堆区空间,而 free 函数是直接释放对象所占的堆区空间,并不会调用对象的析构函数。


运算符重载(Operator Overload)

重新定义运算符的功能(面向对象)。


运算符重载函数也是类中的特殊方法,其方法必须"operator 运算符"这种形式。


运算符重载函数既可以为成员函数,也可以为全局函数,建议尽量使用成员函数。


每个类中都有一个默认的赋值运算符重载函数,它实现的是浅拷贝效果,如果不能满足需求,我们可以自己重载它,

五个不可重载的运算符:

  1. .(成员运算符),通常用于访问对象的成员
  2. ::(作用域运算符)
  3. .*(成员指针运算符),即成员是指针类型,访问指针类型成员指向的数据。


  4. ?: (条件运算符)
  5. sizeof(求长度运算符)

仿函数(Functor):重载小括号运算符,所有对象可以像函数调用一样的形式使用。


设计思想:高类聚、低耦合

友元(Friend)

在一个类的友元中可以访问该类的所有成员,如同本类中一样。


友元分为两种:

临时无名对象

生命周期很短,昙花一现,定义它的语句执行完毕就被释放了。


对象类型转换问题

explicit 关键字:用于修饰构造函数(主要是那些带一个参数的构造函数),表示必须显式调用该构造函数,不会被隐式调用;

带一个参数的构造函数可以用于类型转换,即将其他类型数据转型为对象。


通过重载类型转换运算符(类型转换函数)可以实现将对象转型为其他类型。


隐式调用:类名 p =5; //此时这个5作为一个临时无名的对象,被创建赋给p,然后立马被释放。


显式调用:利用 explicit 关键字修饰改造函数,在定义对象时,必须严格按照构造函数参数列表来写

  1. 类名 p {5};
  2. 类名 p (5);

注:一般情况下,出现在带一个参数的构造函数中,使编译器选择为难。


实例一:malloc/free-new/delete

#include 
#include 
using namespace std;

class Person
{
private:
    int p_sno = 0;
    char* p_name = nullptr;
public:
    Person()
    {
        p_name = new char[20];
        p_name[0]= ';'}
    Person
    (int, snoconstchar *) name:p_sno()sno=
    {
        name char new [20];strcpy
        (,p_name)name;}
    void
    show (void)const <<
    {
        cout << p_sno " " << << p_name ; endl}
    //拷贝构造函数
    
    Person
    (const& Person )p//引用 // 浅拷贝:直接将对象属性的值赋给新对象的属性
    {
        // memcpy(&p_sno,&(p.p_sno),sizeof(p_sno));
        // memcpy(&p_name,&(p.p_name),sizeof(p_sno));
        // memcpy(this, &p, sizeof(p));
        // 深拷贝:如果属性为指针,则将指针指向空间的内容赋给新对象指针空间的内容

        =
        p_name char new [20];// p_sno = p.p_sno;
        memcpy
        (&,p_sno&(.p)p_sno,sizeof()p_sno);memcpy
        (,p_name.p,p_name20);} 
    //重载 赋值 = 运算符

    &
    Person= operator(const& Person) pmemcpy
    {
        (,p_name.p,p_name20);=
        p_sno . p;p_snoreturn
        * ;this}
    ~



    Person()<<
    {
        cout << p_name "快死了" << ; endl// delete 内部实现:
        [
        // 先调用析构函数,等析构函数返回后,才会释放。


// delete this;此时会无限递归,导致栈溢出。


delete]; p_name//p_name为数组 } } ;void show1 ()Person p;//传对象 void show2 (&Person) p;//传对象引用 create Person ();int main ()// molloc与free属于函数,new/delete 属于运算符 { // Person* p1 = (Person*)malloc(sizeof(Person)); // free(p1); // p1->show(); //Person p(1001,"zz"); // //show1(p); // show2(p); // Person p = create(); // cout << &p << endl; ; Person p1//Person p2 = p1; //创建P2用拷贝构造函数等效于:Person p2 {p1} ; Person p2= p1 ; p2//调用无参构造函数 // cout << &p1 << endl; // cout << &p2 << endl; return 0 ;} void show1 ()Person p// 内部实现:Person p = p1;相当于创建了一个布局的对象,浪费资源,时间 { . pshow();} void show2 (&Person) p. { pshow();} create Person ()p { Person (1002,"李四");<< cout & <<p ; endlreturn ; p} #

实例二:友元

include; 
using namespace std;

class B:

class A
{
privateint
    ; avoid

    show_a ()<<
    {
        cout << a ; endl*

        B; b}
    // 将 B 类声明为当前类的友元类

    ;
    friend class B}
;:

class B
{
publicvoid
    show_b ();
    {
        A a.
        a=a 3 ;.
        ashow_a();}
    }
;int

main ();
{
    B b.

    bshow_b();return

    0 ;}
#

实例三:重载 *** 作符

include# 
include; 

using namespace std:

class Student
{
privateint
    ; sno;
    string name:
publicStudent
    ():sno(0),name("")}
    {
    Student

    (int, sno)string name:sno()sno,name ()name}
    {
    Student

    explicit (int) sno:sno()sno,name ("匿名")<<
    {
        cout "Student(int)" << ; endl}
    ~

    Student()<<
    {
        cout << sno ' ' << << name " ~Student()" << ; endl}
    void

    show ()const <<
    {
        cout << sno ' ' << << name ; endl}
    int

    getSno ()const return
    {
        ; sno}
    //运算符重载(Operator Overload)

  
    
    (

    //  重载比较(>)运算符                        //左 *** 作数只能为类、结构体、共用体
    bool operator >int) i;double       //> 属于双目运算符,右 *** 作数为传入的参数      
    
    ( operator >const& Student )sreturn{
        3.14 ;}
    <
    bool operator(const& Student) sreturn
    {
        < sno . s;sno}
    (

    bool operator>=int) ireturn
    {
        ; sno >= i}
    //  单目运算符

    //  前后置运算符对于非对象的 *** 作效率一样
    //  重载前置++p,p为对象;
    //  对于对象,前置运算符效率高一些,后置低一些。


& Student++ operator()++ { sno;return * ;this} // 重载后置p++ ++ Student operator(int)//参数写一个int,编译器认为是后置,此参数为 “哑元” 参数 = { Student tmp * ;this++ sno;return ; tmp} // 重载下标运算符 char [ operator](int) ireturn { [ name]i;} // 重载下标运算符:实现名字判断 [ string operator](constchar *) iif { (strcmp(,i"name")== 0 )return ; nameelse return "error" ;} // 重载(强制)类型转换运算符 int operator ()return { ; sno} // 重载加法运算符 + Student operator(const& Student) s; { Student tmp. tmp=sno + sno . s;sno. tmp=name + name . s;namereturn ; tmp} // 重载括号运算符 int operator ()(int, iint ) jreturn { 5 ;} // 声明友元函数 & friend istream( operator>>&istream, in&Student )s;& friend ostream<< operator(&ostream, outconst & Student) s;} ;// 重载 比较运算符的定义 :: bool Student(operator >int) ireturn //> 属于双目运算符,左 *** 作数为对象,右 *** 作数为传入的 { ; sno > i} // 重载 ( bool operator>=int, iconst& Student) s//全局 return { . i >= sgetSno();} //使用运算符时没有指定,先在类中找符合项,没有找到再去全局区 & istream( operator>>&istream, in& Student) s<< { cout "学号:" ;// int sno; // //法一:setSno()传递,不太靠谱 // in >> sno; . in >> s;sno//法二:友元函数 << cout "姓名:" ;. in >> s;namereturn ; in} & ostream<< operator(&ostream, outconst & Student) s<< { out . s<<sno ' ' << . s<<name ;endlreturn ; out} int main ()// // (++p1).show(); { // // (p1++).show(); // // p1.show(); // // // p1 = p2; // // 100 >= p2; // operator>=(100, p2); // // p2 >= 100; // p2.operator>=(100); operator>=(p2, 100); // // cout << d << endl; // // double d = (p1 > p2); // double d = (p1.operator>(p2)); // // if(p1 < p2) // if(p1.operator<(p2)) // // cout << "yes" << endl; // // { // // } // Student p1,p2; // // p1 > 1000; // p1.operator(1000); // p1 = p2; // cout << "yes" << endl; // if(p1 > p2) //if(p1.operator<(p2)) // { // } // p1 + p2; // p1 - p2; // p1 && p2; // p1 > p2; // p1[3]; // int i = int(p1); s2 Student (3);// Student s2(3); = s2 Student (5);// 仿函数(Functor) << cout s2 (10,9 )<< ; endl// 括号运算符 // 临时无名对象,生命周期很短 // Student(1001, "李四").show(); p1 Student (1001,"zhangsan"),1002p2 {,"lisi"};<< cout << p1 ; endl//先判断 << 是否有重载方法,再判断 p1是否有重载方法(类型转换) // cout << (int)(p1) < // cout << int(p2) << endl; // cout << p2["name"] << endl; // cout << p1[2] < return 0 ;} [+++]

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
C++编程基础——newdelete与mallocfree区别、运算符重载等_C_内存溢出

C++编程基础——newdelete与mallocfree区别、运算符重载等

C++编程基础——newdelete与mallocfree区别、运算符重载等,第1张

new/delete 和malloc/free 的区别

共同点:

功能相同,new 和malloc 都是在堆区申请指定大小的内存空间,delete 和 free 都是释放指定的一块堆区内存空间(内部实现细节不同,不要混用)。


不同点:

new 和 delete 是 C++中新增的运算符,而malloc 和 free 是函数,所以运算符的执行效率比函数高(对于非对象数据)。


对于非对象数据,它们基本没有区别。


对于对象数据:

  1. 使用 new 运算符在堆区给对象申请空间后,还会调用对像的某个匹配的构造函数,而malloc 函数仅仅就是给对象申请堆区空间,并不会调用其构造函数。


  2. 使用 delete 运算符释放对象时,它首先会调用一次该对象的析构函数,然后再释放对象所占的堆区空间,而 free 函数是直接释放对象所占的堆区空间,并不会调用对象的析构函数。


运算符重载(Operator Overload)

重新定义运算符的功能(面向对象)。


运算符重载函数也是类中的特殊方法,其方法必须"operator 运算符"这种形式。


运算符重载函数既可以为成员函数,也可以为全局函数,建议尽量使用成员函数。


每个类中都有一个默认的赋值运算符重载函数,它实现的是浅拷贝效果,如果不能满足需求,我们可以自己重载它,

五个不可重载的运算符:

  1. .(成员运算符),通常用于访问对象的成员
  2. ::(作用域运算符)
  3. .*(成员指针运算符),即成员是指针类型,访问指针类型成员指向的数据。


  4. ?: (条件运算符)
  5. sizeof(求长度运算符)

仿函数(Functor):重载小括号运算符,所有对象可以像函数调用一样的形式使用。


设计思想:高类聚、低耦合

  • 高类聚是指一个模块内部各个元素之间关系紧密,争取用最少的元素和方法实现相应的功能。


  • 低耦合是指一个程序中各个模块之间的联系少和相互依赖程度低
友元(Friend)

在一个类的友元中可以访问该类的所有成员,如同本类中一样。


友元分为两种:

  • 友元函数
  • 友元类
临时无名对象

生命周期很短,昙花一现,定义它的语句执行完毕就被释放了。


对象类型转换问题

explicit 关键字:用于修饰构造函数(主要是那些带一个参数的构造函数),表示必须显式调用该构造函数,不会被隐式调用;

带一个参数的构造函数可以用于类型转换,即将其他类型数据转型为对象。


通过重载类型转换运算符(类型转换函数)可以实现将对象转型为其他类型。


隐式调用:类名 p =5; //此时这个5作为一个临时无名的对象,被创建赋给p,然后立马被释放。


显式调用:利用 explicit 关键字修饰改造函数,在定义对象时,必须严格按照构造函数参数列表来写

  1. 类名 p {5};
  2. 类名 p (5);

注:一般情况下,出现在带一个参数的构造函数中,使编译器选择为难。


实例一:malloc/free-new/delete

#include 
#include 
using namespace std;

class Person
{
private:
    int p_sno = 0;
    char* p_name = nullptr;
public:
    Person()
    {
        p_name = new char[20];
        p_name[0]= ';'}
    Person
    (int, snoconstchar *) name:p_sno()sno=
    {
        name char new [20];strcpy
        (,p_name)name;}
    void
    show (void)const <<
    {
        cout << p_sno " " << << p_name ; endl}
    //拷贝构造函数
    
    Person
    (const& Person )p//引用 // 浅拷贝:直接将对象属性的值赋给新对象的属性
    {
        // memcpy(&p_sno,&(p.p_sno),sizeof(p_sno));
        // memcpy(&p_name,&(p.p_name),sizeof(p_sno));
        // memcpy(this, &p, sizeof(p));
        // 深拷贝:如果属性为指针,则将指针指向空间的内容赋给新对象指针空间的内容

        =
        p_name char new [20];// p_sno = p.p_sno;
        memcpy
        (&,p_sno&(.p)p_sno,sizeof()p_sno);memcpy
        (,p_name.p,p_name20);} 
    //重载 赋值 = 运算符

    &
    Person= operator(const& Person) pmemcpy
    {
        (,p_name.p,p_name20);=
        p_sno . p;p_snoreturn
        * ;this}
    ~



    Person()<<
    {
        cout << p_name "快死了" << ; endl// delete 内部实现:
        [
        // 先调用析构函数,等析构函数返回后,才会释放。


// delete this;此时会无限递归,导致栈溢出。


delete]; p_name//p_name为数组 } } ;void show1 ()Person p;//传对象 void show2 (&Person) p;//传对象引用 create Person ();int main ()// molloc与free属于函数,new/delete 属于运算符 { // Person* p1 = (Person*)malloc(sizeof(Person)); // free(p1); // p1->show(); //Person p(1001,"zz"); // //show1(p); // show2(p); // Person p = create(); // cout << &p << endl; ; Person p1//Person p2 = p1; //创建P2用拷贝构造函数等效于:Person p2 {p1} ; Person p2= p1 ; p2//调用无参构造函数 // cout << &p1 << endl; // cout << &p2 << endl; return 0 ;} void show1 ()Person p// 内部实现:Person p = p1;相当于创建了一个布局的对象,浪费资源,时间 { . pshow();} void show2 (&Person) p. { pshow();} create Person ()p { Person (1002,"李四");<< cout & <<p ; endlreturn ; p} #

实例二:友元

include; 
using namespace std;

class B:

class A
{
privateint
    ; avoid

    show_a ()<<
    {
        cout << a ; endl*

        B; b}
    // 将 B 类声明为当前类的友元类

    ;
    friend class B}
;:

class B
{
publicvoid
    show_b ();
    {
        A a.
        a=a 3 ;.
        ashow_a();}
    }
;int

main ();
{
    B b.

    bshow_b();return

    0 ;}
#

实例三:重载 *** 作符

include# 
include; 

using namespace std:

class Student
{
privateint
    ; sno;
    string name:
publicStudent
    ():sno(0),name("")}
    {
    Student

    (int, sno)string name:sno()sno,name ()name}
    {
    Student

    explicit (int) sno:sno()sno,name ("匿名")<<
    {
        cout "Student(int)" << ; endl}
    ~

    Student()<<
    {
        cout << sno ' ' << << name " ~Student()" << ; endl}
    void

    show ()const <<
    {
        cout << sno ' ' << << name ; endl}
    int

    getSno ()const return
    {
        ; sno}
    //运算符重载(Operator Overload)

  
    
    (

    //  重载比较(>)运算符                        //左 *** 作数只能为类、结构体、共用体
    bool operator >int) i;double       //> 属于双目运算符,右 *** 作数为传入的参数      
    
    ( operator >const& Student )sreturn{
        3.14 ;}
    <
    bool operator(const& Student) sreturn
    {
        < sno . s;sno}
    (

    bool operator>=int) ireturn
    {
        ; sno >= i}
    //  单目运算符

    //  前后置运算符对于非对象的 *** 作效率一样
    //  重载前置++p,p为对象;
    //  对于对象,前置运算符效率高一些,后置低一些。


& Student++ operator()++ { sno;return * ;this} // 重载后置p++ ++ Student operator(int)//参数写一个int,编译器认为是后置,此参数为 “哑元” 参数 = { Student tmp * ;this++ sno;return ; tmp} // 重载下标运算符 char [ operator](int) ireturn { [ name]i;} // 重载下标运算符:实现名字判断 [ string operator](constchar *) iif { (strcmp(,i"name")== 0 )return ; nameelse return "error" ;} // 重载(强制)类型转换运算符 int operator ()return { ; sno} // 重载加法运算符 + Student operator(const& Student) s; { Student tmp. tmp=sno + sno . s;sno. tmp=name + name . s;namereturn ; tmp} // 重载括号运算符 int operator ()(int, iint ) jreturn { 5 ;} // 声明友元函数 & friend istream( operator>>&istream, in&Student )s;& friend ostream<< operator(&ostream, outconst & Student) s;} ;// 重载 比较运算符的定义 :: bool Student(operator >int) ireturn //> 属于双目运算符,左 *** 作数为对象,右 *** 作数为传入的 { ; sno > i} // 重载 ( bool operator>=int, iconst& Student) s//全局 return { . i >= sgetSno();} //使用运算符时没有指定,先在类中找符合项,没有找到再去全局区 & istream( operator>>&istream, in& Student) s<< { cout "学号:" ;// int sno; // //法一:setSno()传递,不太靠谱 // in >> sno; . in >> s;sno//法二:友元函数 << cout "姓名:" ;. in >> s;namereturn ; in} & ostream<< operator(&ostream, outconst & Student) s<< { out . s<<sno ' ' << . s<<name ;endlreturn ; out} int main ()// // (++p1).show(); { // // (p1++).show(); // // p1.show(); // // // p1 = p2; // // 100 >= p2; // operator>=(100, p2); // // p2 >= 100; // p2.operator>=(100); operator>=(p2, 100); // // cout << d << endl; // // double d = (p1 > p2); // double d = (p1.operator>(p2)); // // if(p1 < p2) // if(p1.operator<(p2)) // // cout << "yes" << endl; // // { // // } // Student p1,p2; // // p1 > 1000; // p1.operator(1000); // p1 = p2; // cout << "yes" << endl; // if(p1 > p2) //if(p1.operator<(p2)) // { // } // p1 + p2; // p1 - p2; // p1 && p2; // p1 > p2; // p1[3]; // int i = int(p1); s2 Student (3);// Student s2(3); = s2 Student (5);// 仿函数(Functor) << cout s2 (10,9 )<< ; endl// 括号运算符 // 临时无名对象,生命周期很短 // Student(1001, "李四").show(); p1 Student (1001,"zhangsan"),1002p2 {,"lisi"};<< cout << p1 ; endl//先判断 << 是否有重载方法,再判断 p1是否有重载方法(类型转换) // cout << (int)(p1) < // cout << int(p2) << endl; // cout << p2["name"] << endl; // cout << p1[2] < return 0 ;}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/562262.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-01
下一篇 2022-04-01

发表评论

登录后才能评论

评论列表(0条)

保存