Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;用指针复制构造函数_C++_Copy Constructor_Deep Copy - Fatal编程技术网

C++ C++;用指针复制构造函数

C++ C++;用指针复制构造函数,c++,copy-constructor,deep-copy,C++,Copy Constructor,Deep Copy,我理解深度复制指针的必要性(在需要对象的完整副本的情况下),我的困惑来自以下(完全虚构的示例) 分配内存,然后当我们说:New=Orig我预计会出现内存泄漏,因为如果我盲目地更新m_piRandom=newint(*toAssign.m_piRandom)我会丢失它之前指向的内存 因此,我决定在赋值运算符中输入以下内容: if (m_piRandom) { // Need to free this memory!

我理解深度复制指针的必要性(在需要对象的完整副本的情况下),我的困惑来自以下(完全虚构的示例)

分配内存,然后当我们说:
New=Orig我预计会出现内存泄漏,因为如果我盲目地更新
m_piRandom=newint(*toAssign.m_piRandom)我会丢失它之前指向的内存

因此,我决定在赋值运算符中输入以下内容:

if (m_piRandom)
            {
                // Need to free this memory! 
                delete m_piRandom;
                m_piRandom = NULL;
            }
a& a::operator=(const a &toAssign)
{
    if (this != &toAssign)
    {
        m_sz = toAssign.m_sz;
        if (m_piRandom)           //<<<<< No need to check this as it should always be
        {                         //<<<<< initialized by constructors.
            delete m_piRandom;    
            m_piRandom = NULL;
        }

        m_piRandom = new int(*toAssign.m_piRandom);
    }
    return *this;
}
当调用以下内容时(第一行!)
a Orig=a(“原始”)调用复制构造函数(我称之为赋值运算符以减少重复),指针
m_piRandom
设置为0xcccc。不为空。因此,它试图删除从未分配的内存。我希望它在到达
New=Orig时能够工作

谢谢

代码的问题在于复制构造函数没有初始化int指针membrer,但赋值运算符假定它的值正确。因此,在调用赋值运算符之前,只需在复制构造函数中初始化指向0的int指针。

您的第一个错误是根据赋值运算符实现了复制构造函数。复制构造函数基于其他对象创建一个新对象,而赋值运算符则清除并更改已创建对象的位

因此,正确的复制构造函数应该是:-

a::a(const a &toCopy) : m_sz(toCopy.m_sz), m_piRandom(new int)
{
    *m_piRandom = toCopy.m_piRandom;
}
实施此操作后,您可以简化赋值运算符:

if (m_piRandom)
            {
                // Need to free this memory! 
                delete m_piRandom;
                m_piRandom = NULL;
            }
a& a::operator=(const a &toAssign)
{
    if (this != &toAssign)
    {
        m_sz = toAssign.m_sz;
        if (m_piRandom)           //<<<<< No need to check this as it should always be
        {                         //<<<<< initialized by constructors.
            delete m_piRandom;    
            m_piRandom = NULL;
        }

        m_piRandom = new int(*toAssign.m_piRandom);
    }
    return *this;
}

发生此错误的原因是复制构造函数未初始化
m_piRandom
。这意味着变量将(很可能)充满垃圾(初始化对象时内存位置的任何内容)

调用顺序如下所示:

a::a() [doesn not initialize m_piRandom] -> a::operator= -> delete m_piRandom.
要修复:

a::a(const a &toCopy)
: m_piRandom{ nullptr } // <---- add this
{
    operator=(toCopy);
}
a::a(常数a&toCopy)

:m_piRandom{nullptr}//注意,
new int(*toAssign.m_piRandom)
分配一个整数,并将其初始化为
*toAssign.m_piRandom
。至于您的问题,您不能对复制构造函数和复制赋值运算符使用完全相同的代码,因为您注意到,语义有一点不同。不过,您只需在copy-constructor中初始化指针即可解决此问题。您的意思肯定是
a::a(const a&toCopy):m_piRandom(nullptr){operator=(toCopy);}
。感谢各位,我做了此更改,调用赋值运算符以省去所有赋值的麻烦没有什么错,假设我总是初始化复制构造函数的初始化器列表中的成员?建议的赋值运算符存在内存泄漏。我建议使用复制和交换。这是最好的选择,但我认为实现这一点的道路首先要明确区分分配/复制操作。这就是为什么我刚刚澄清了代码中的问题…直到那时,我们漂亮的析构函数必须承担更多的责任。很明显,船长,你能解释一下如何在不使用复制和交换的情况下消除赋值运算符中的内存泄漏吗?感谢
int*tmp(新int(*toAssign.m_piRandom));标准:交换(m_piRandom,tmp);删除tmp
应该做一些技巧,或者如果没有使用std::swap(我的公司不使用std库,我的示例是为了便于理解),我可以只检查m_piRandom在赋值中是否为NULL,如果没有,在赋值之前删除它,按照我原来的示例?
a::a(const a &toCopy)
: m_piRandom{ nullptr } // <---- add this
{
    operator=(toCopy);
}