Error[8]: Undefined offset: 881, 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(

实现一个string类 代码如下
#include 
#include 

using namespace std;

class myString{
public:
    //构造函数
    myString(const char* str = NULL);
    //拷贝构造函数
    myString(const myString& str);
    //赋值 *** 作
    myString& operator=(const myString& str);
    ~myString();
    void show();

private:
    char* m_data;
};

myString::myString(const char* str) {
    if (str == NULL) {
        m_data = new char[1];
        if (m_data == nullptr) {
            cout << "memory allocate failed!" << endl;
            exit(1);
        }
        m_data[0] = ';'}
    else = {
        m_data new char [strlen()str+ 1 ];if
        ( ==m_data nullptr )<< {
            cout "memory allocate failed!" << ; endlexit
            (1);}
        strcpy
        (,m_data) str;}
    }
::

myStringmyString(const& myString) str= {
    m_data new char [strlen(.str)m_data+ 1 ];if
    ( ==m_data nullptr )<< {
        cout "memory allocate failed!" << ; endlexit
        (1);}
    strcpy
    (,m_data. str)m_data;}
&

myString:: myStringoperator=(const& myString) strif {
    ( this== & )strreturn * this;delete
    []; m_data=

    m_data new char [strlen(.str)m_data+ 1 ];if
    ( ==m_data nullptr )<< {
        cout "memory allocate failed!" << ; endlexit
        (1);}
    strcpy
    (,m_data. str)m_data;return
    * this;}
myString

::~myString()delete {
    []; m_data}
void

:: myStringshow()<< {
    cout << m_data ; endl}
int

main (); {
    myString ac
    myString ("asdf");b
    myString ()c;=
    a ; c.
    ashow();.
    bshow();.
    cshow();return
    0 ;}
int
考察的点

对于类的构造函数,赋值拷贝函数的考察

为什么需要拷贝构造函数?

这里就涉及到一个深、浅拷贝的问题了。



首先来看下拷贝构造函数是干什么用的。


拷⻉构造函数的函数参数为对象本身的引⽤,⽤于根据⼀个已存在的对象复制 出⼀个新的该类的对象,⼀般在函数中会将已存在的对象的数据成员的值⼀⼀复制到新创建的 对象中。


如果没有自己定义拷⻉构造函数,则系统会默认创建⼀个拷⻉构造函数,但当类中有 指针成员时,最好不要使⽤编译器提供的默认的拷⻉构造函数,最好⾃⼰定义并且在函数中执 ⾏深拷⻉。


我们可以通过上面给出的例子来看

main (); {
    myString ac
    myString ("asdf");b
    myString ()c;=
    a ; c.
    ashow();.
    bshow();.
    cshow();return
    0 ;}
myString

在main函数中初始化了三个对象,其中a调用默认构造函数,c也是(自己调试一下就知道了),而b却是使用拷贝构造函数

如果在拷贝构造函数中并不是单纯的复制指针的值,而是重新分配一片内存。


内存地址如下:

这里的b,c的m_data指向的是不同的内存地址并且都相差0x20 即32个bit即4个字节
这样的话在析构函数(如下):delete是不会出现问题的。


内存是正常的释放的。


::~myString()delete {
    []; m_data}
struct

但是如果不使用系统默认的拷贝构造函数的话:


这里就会发现b和c的m_data指向了同一片内存地址,这样的话在执行析构函数的时候就会对同一个地址delete两次。


导致野指针的问题。


链表相关 单链表

企业一般不会考察静态链表

代码:

pNode int
{
    ; data*
    pNode ;nextpNode
    (int) _data:data()_data,next (NULL)}{/* data */
    }
*;headvoid

addpHead (int) val* {
    pNode =p new pNode ()val;=
    p->next ; head->next=
    head->next ; p}
void
//删除p后面的节点,即p->left
premove (*pNode )p* {
    pNode =tmp ; p->next=
    p->next ; p->next->nextdelete
    ; tmp}
struct

双链表
tNode int
{
    , key; val*
    tNode ,left* ;righttNode
    (int, _keyint ) _val:key()_key,val ()_val,left (NULL),right (NULL)} {/* data */
    }
*,L* ;R//删除p节点,不需要知道之前的节点
void
tremove (*tNode )p= {
    p->right->left ; p->left=
    p->left->right ; p->right}
//在左节点插入
void
Linsert (*tNode )p= {
    p->right ; L->right=
    p->left ; L=
    L->right->left ; p=
    L->right ; p}
//在右端点插入
void
Rinsert (*tNode )p= {
    p->left ; R->left=
    p->right ; R=
    R->left->right ; p=
    R->left ; p}
#
智能指针

代码如下:

include# 
include# 
includeusing 
namespace ; stdtemplate
< typenameT class>
SharedPtr private{
:*
    T ;m_ptr_//内部指针,保证拷贝指向同一内存        *
    size_t ;m_count_public

://构造函数
SharedPtr
    (): m_ptr_ (nullptr),m_count_ (new) size_t} {SharedPtr
    (*T )p: m_ptr_ ()p,m_count_ (new) size_tif{
        ( ==p nullptr )= {
            m_count_ 0 ;}
        else = {
            m_count_ 1 ;}
        }
    //析构函数
~
    SharedPtr()if {
        ( this)->m_ptr_if {
            ( --(*)m_count_== 0 )delete {
                ; m_count_delete
                ; m_ptr_=
                m_count_ nullptr ;=
                m_ptr_ nullptr ;}
            }
        }
    //拷贝赋值函数
    SharedPtr
    (const& SharedPtr) ptrif {
        ( this!= ) ptrthis {
            =->m_ptr_ . ptr;m_ptr_this
            =->m_count_ . ptr;m_count_(
            *this)->m_count_++ ;}
        }
    //赋值拷贝重载=
    &
    SharedPtr operator=(const& SharedPtr) ptr//防止自我赋值 {
        if
        ( this==->m_ptr_ . ptr)m_ptr_return {
            * this;}
        if
        ( this)->m_ptr_if {
            ( --(*this)->m_count_== 0 )delete {
                ; m_count_delete
                ; m_ptr_=
                m_count_ nullptr ;=
                m_ptr_ nullptr ;}
            } 
        =
        m_ptr_ . ptr;m_ptr_=
        m_count_ . ptr;m_count_(
        *)m_count_++;return
        * this;}
    //移动构造函数
    SharedPtr
    (&&SharedPtr) ptr= {
        m_ptr_ . ptr;m_ptr_=
        m_count_ . ptr;m_count_++
        (*)m_count_;}
    //移动赋值运算
    void
    operator =(&&SharedPtr) ptrSharedPtr {
        (::stdmove()ptr);}
    &
    //重载->
    Toperator (->)if {
        ( this)->m_ptr_return this ;->m_ptr_}
    //重载*
    &
    Toperator *()if {
        ( this)->m_ptr_return * (this)->m_ptr_;}
    //返回用户个数
    use_count
    size_t ()return {
        * (this)->m_count_;}
    }
;void

Std_shared_ptr_test ()< {
    shared_ptrintptr>(newint );<
    shared_ptrintptr2>()ptr;<
    shared_ptrint;> ptr3=
    ptr3 ; ptr2<<

    cout "这是std::shared_ptr测试结果:" << ; endl<<
	cout "ptr.use_count:"<<.ptruse_count()<< ; endl<<
	cout "ptr2.use_count:"<<. ptr2use_count()<< ; endl<<
	cout "ptr3.use_count:"<<. ptr3use_count()<< ; endl*

    =ptr3 100 ;<<
    cout "通过对*ptr3赋值 取ptr的值为:" <<*<<ptr ; endl<<
	cout ; endl}

void

Shared_ptr_Test ()< {
    SharedPtrintptr>(newint );<
    SharedPtrintptr2>()ptr;<
    SharedPtrint;>ptr3=
    ptr3 ; ptr2<<

    cout "这是std::shared_ptr测试结果:" << ; endl<<
	cout "ptr.use_count:"<<.ptruse_count()<< ; endl<<
	cout "ptr2.use_count:"<<. ptr2use_count()<< ; endl<<
	cout "ptr3.use_count:"<<. ptr3use_count()<< ; endl*

    =ptr3 100 ;<<
    cout "通过对*ptr3赋值 取ptr的值为:" <<*<<ptr ; endl<<
	cout ; endl}
int

main ()// std::string s = "hello world"; {
    // auto left = std::move(s);
    // std::cout << left << std::endl;
    // std::cout << s << std::endl;
    Shared_ptr_Test
    ();Std_shared_ptr_test
    ();return
    0 ;}
[+++]

shared_ptr实现共享式拥有概念,多个智能指针可以指向相同对象,该对象和其相关资源会在最后一个引用被销毁时候释放

使用计数机制来表明资源被几个指针共享。


)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, 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++面试题代码-未完待续】_C_内存溢出

【常见的C++面试题代码-未完待续】

【常见的C++面试题代码-未完待续】,第1张

实现一个string类 代码如下
#include 
#include 

using namespace std;

class myString{
public:
    //构造函数
    myString(const char* str = NULL);
    //拷贝构造函数
    myString(const myString& str);
    //赋值 *** 作
    myString& operator=(const myString& str);
    ~myString();
    void show();

private:
    char* m_data;
};

myString::myString(const char* str) {
    if (str == NULL) {
        m_data = new char[1];
        if (m_data == nullptr) {
            cout << "memory allocate failed!" << endl;
            exit(1);
        }
        m_data[0] = ';'}
    else = {
        m_data new char [strlen()str+ 1 ];if
        ( ==m_data nullptr )<< {
            cout "memory allocate failed!" << ; endlexit
            (1);}
        strcpy
        (,m_data) str;}
    }
::

myStringmyString(const& myString) str= {
    m_data new char [strlen(.str)m_data+ 1 ];if
    ( ==m_data nullptr )<< {
        cout "memory allocate failed!" << ; endlexit
        (1);}
    strcpy
    (,m_data. str)m_data;}
&

myString:: myStringoperator=(const& myString) strif {
    ( this== & )strreturn * this;delete
    []; m_data=

    m_data new char [strlen(.str)m_data+ 1 ];if
    ( ==m_data nullptr )<< {
        cout "memory allocate failed!" << ; endlexit
        (1);}
    strcpy
    (,m_data. str)m_data;return
    * this;}
myString

::~myString()delete {
    []; m_data}
void

:: myStringshow()<< {
    cout << m_data ; endl}
int

main (); {
    myString ac
    myString ("asdf");b
    myString ()c;=
    a ; c.
    ashow();.
    bshow();.
    cshow();return
    0 ;}
int
考察的点

对于类的构造函数,赋值拷贝函数的考察

为什么需要拷贝构造函数?

这里就涉及到一个深、浅拷贝的问题了。



首先来看下拷贝构造函数是干什么用的。


拷⻉构造函数的函数参数为对象本身的引⽤,⽤于根据⼀个已存在的对象复制 出⼀个新的该类的对象,⼀般在函数中会将已存在的对象的数据成员的值⼀⼀复制到新创建的 对象中。


如果没有自己定义拷⻉构造函数,则系统会默认创建⼀个拷⻉构造函数,但当类中有 指针成员时,最好不要使⽤编译器提供的默认的拷⻉构造函数,最好⾃⼰定义并且在函数中执 ⾏深拷⻉。


我们可以通过上面给出的例子来看

main (); {
    myString ac
    myString ("asdf");b
    myString ()c;=
    a ; c.
    ashow();.
    bshow();.
    cshow();return
    0 ;}
myString

在main函数中初始化了三个对象,其中a调用默认构造函数,c也是(自己调试一下就知道了),而b却是使用拷贝构造函数

如果在拷贝构造函数中并不是单纯的复制指针的值,而是重新分配一片内存。


内存地址如下:

这里的b,c的m_data指向的是不同的内存地址并且都相差0x20 即32个bit即4个字节
这样的话在析构函数(如下):delete是不会出现问题的。


内存是正常的释放的。


::~myString()delete {
    []; m_data}
struct

但是如果不使用系统默认的拷贝构造函数的话:


这里就会发现b和c的m_data指向了同一片内存地址,这样的话在执行析构函数的时候就会对同一个地址delete两次。


导致野指针的问题。


链表相关 单链表

企业一般不会考察静态链表

代码:

pNode int
{
    ; data*
    pNode ;nextpNode
    (int) _data:data()_data,next (NULL)}{/* data */
    }
*;headvoid

addpHead (int) val* {
    pNode =p new pNode ()val;=
    p->next ; head->next=
    head->next ; p}
void
//删除p后面的节点,即p->left
premove (*pNode )p* {
    pNode =tmp ; p->next=
    p->next ; p->next->nextdelete
    ; tmp}
struct

双链表
tNode int
{
    , key; val*
    tNode ,left* ;righttNode
    (int, _keyint ) _val:key()_key,val ()_val,left (NULL),right (NULL)} {/* data */
    }
*,L* ;R//删除p节点,不需要知道之前的节点
void
tremove (*tNode )p= {
    p->right->left ; p->left=
    p->left->right ; p->right}
//在左节点插入
void
Linsert (*tNode )p= {
    p->right ; L->right=
    p->left ; L=
    L->right->left ; p=
    L->right ; p}
//在右端点插入
void
Rinsert (*tNode )p= {
    p->left ; R->left=
    p->right ; R=
    R->left->right ; p=
    R->left ; p}
#
智能指针

代码如下:

include# 
include# 
includeusing 
namespace ; stdtemplate
< typenameT class>
SharedPtr private{
:*
    T ;m_ptr_//内部指针,保证拷贝指向同一内存        *
    size_t ;m_count_public

://构造函数
SharedPtr
    (): m_ptr_ (nullptr),m_count_ (new) size_t} {SharedPtr
    (*T )p: m_ptr_ ()p,m_count_ (new) size_tif{
        ( ==p nullptr )= {
            m_count_ 0 ;}
        else = {
            m_count_ 1 ;}
        }
    //析构函数
~
    SharedPtr()if {
        ( this)->m_ptr_if {
            ( --(*)m_count_== 0 )delete {
                ; m_count_delete
                ; m_ptr_=
                m_count_ nullptr ;=
                m_ptr_ nullptr ;}
            }
        }
    //拷贝赋值函数
    SharedPtr
    (const& SharedPtr) ptrif {
        ( this!= ) ptrthis {
            =->m_ptr_ . ptr;m_ptr_this
            =->m_count_ . ptr;m_count_(
            *this)->m_count_++ ;}
        }
    //赋值拷贝重载=
    &
    SharedPtr operator=(const& SharedPtr) ptr//防止自我赋值 {
        if
        ( this==->m_ptr_ . ptr)m_ptr_return {
            * this;}
        if
        ( this)->m_ptr_if {
            ( --(*this)->m_count_== 0 )delete {
                ; m_count_delete
                ; m_ptr_=
                m_count_ nullptr ;=
                m_ptr_ nullptr ;}
            } 
        =
        m_ptr_ . ptr;m_ptr_=
        m_count_ . ptr;m_count_(
        *)m_count_++;return
        * this;}
    //移动构造函数
    SharedPtr
    (&&SharedPtr) ptr= {
        m_ptr_ . ptr;m_ptr_=
        m_count_ . ptr;m_count_++
        (*)m_count_;}
    //移动赋值运算
    void
    operator =(&&SharedPtr) ptrSharedPtr {
        (::stdmove()ptr);}
    &
    //重载->
    Toperator (->)if {
        ( this)->m_ptr_return this ;->m_ptr_}
    //重载*
    &
    Toperator *()if {
        ( this)->m_ptr_return * (this)->m_ptr_;}
    //返回用户个数
    use_count
    size_t ()return {
        * (this)->m_count_;}
    }
;void

Std_shared_ptr_test ()< {
    shared_ptrintptr>(newint );<
    shared_ptrintptr2>()ptr;<
    shared_ptrint;> ptr3=
    ptr3 ; ptr2<<

    cout "这是std::shared_ptr测试结果:" << ; endl<<
	cout "ptr.use_count:"<<.ptruse_count()<< ; endl<<
	cout "ptr2.use_count:"<<. ptr2use_count()<< ; endl<<
	cout "ptr3.use_count:"<<. ptr3use_count()<< ; endl*

    =ptr3 100 ;<<
    cout "通过对*ptr3赋值 取ptr的值为:" <<*<<ptr ; endl<<
	cout ; endl}

void

Shared_ptr_Test ()< {
    SharedPtrintptr>(newint );<
    SharedPtrintptr2>()ptr;<
    SharedPtrint;>ptr3=
    ptr3 ; ptr2<<

    cout "这是std::shared_ptr测试结果:" << ; endl<<
	cout "ptr.use_count:"<<.ptruse_count()<< ; endl<<
	cout "ptr2.use_count:"<<. ptr2use_count()<< ; endl<<
	cout "ptr3.use_count:"<<. ptr3use_count()<< ; endl*

    =ptr3 100 ;<<
    cout "通过对*ptr3赋值 取ptr的值为:" <<*<<ptr ; endl<<
	cout ; endl}
int

main ()// std::string s = "hello world"; {
    // auto left = std::move(s);
    // std::cout << left << std::endl;
    // std::cout << s << std::endl;
    Shared_ptr_Test
    ();Std_shared_ptr_test
    ();return
    0 ;}

shared_ptr实现共享式拥有概念,多个智能指针可以指向相同对象,该对象和其相关资源会在最后一个引用被销毁时候释放

使用计数机制来表明资源被几个指针共享。


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

原文地址: http://outofmemory.cn/langs/564179.html

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

发表评论

登录后才能评论

评论列表(0条)

保存