Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.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++_Segmentation Fault_Copy Constructor_Deep Copy_Shallow Copy - Fatal编程技术网

C++ 关于C++;很可能是由自定义副本构造函数引起的

C++ 关于C++;很可能是由自定义副本构造函数引起的,c++,segmentation-fault,copy-constructor,deep-copy,shallow-copy,C++,Segmentation Fault,Copy Constructor,Deep Copy,Shallow Copy,我得到了一个分段错误,我相信这是由复制构造函数引起的。然而,我在网上找不到这样的例子。我读过浅拷贝和深拷贝,但我不确定这本书属于哪一类。有人知道吗 MyObject::MyObject{ lots of things including const and structs, but no pointers } MyObject::MyObject( const MyObject& oCopy){ *this = oCopy;//is this deep or shallo

我得到了一个分段错误,我相信这是由复制构造函数引起的。然而,我在网上找不到这样的例子。我读过浅拷贝和深拷贝,但我不确定这本书属于哪一类。有人知道吗

MyObject::MyObject{
    lots of things including const and structs, but no pointers
}
MyObject::MyObject( const MyObject& oCopy){
    *this = oCopy;//is this deep or shallow?
}
const MyObject& MyObject::operator=(const MyObject& oRhs){
    if( this != oRhs ){
        members = oRhs.members;
        .....//there is a lot of members
    }
    return *this;
}
MyObject::~MyObject(){
    //there is nothing here
}
代码:

编辑:添加运算符=和构造函数


解决方法:错误的树,结果是一个函数在同一个对象上调用了两次delete

这两个函数都是,这取决于
操作符=
的操作。这就是魔法发生的地方;复制构造函数只是在调用它


如果您没有自己定义一个
操作符=
,那么编译器为您合成了一个,并且它正在执行浅层复制。

根据您的代码,您没有创建原始对象。。。您正在创建一个指针,如下所示: 常量MyObject*mpoOriginal


因此,复制正在使用坏数据创建新对象…

您正在做的是使复制构造函数使用赋值运算符(您似乎没有定义)。坦率地说,我很惊讶它能编译,但因为您没有显示所有代码,所以它可能会编译


以正常方式编写复制构造函数,然后查看是否仍然存在相同的问题。如果你说的“很多事情”是真的。。。但是我没有看到任何指针,那么你根本不应该写一个复制构造函数。尝试删除它。

在复制构造函数中使用这样的赋值运算符通常是个坏主意。这将默认构造所有成员,然后分配给它们。最好只依赖隐式生成的复制构造函数,或者使用成员初始值设定项列表复制需要复制的成员,并对其他成员应用适当的初始化


如果没有类成员的详细信息,就很难判断是什么导致了segfault。

我无法直接回答到底是什么导致了segfault,但这里的传统智慧是遵循,即当您发现自己需要任何复制构造函数、赋值运算符或析构函数时,您最好实现这三个功能(添加移动语义,使其成为“四个规则”)

然后,通常是另一种方式——复制赋值操作符是根据复制构造函数实现的

只有当存在指向动态内存的指针时,浅拷贝和深拷贝之间的差异才有意义。如果这些成员结构中的任何一个没有对其指针进行深度复制,那么您就必须解决这个问题(如何处理取决于结构)。但是,如果所有成员要么不包含指针,要么正确地进行了指针的深度复制,那么复制构造函数/赋值就不是问题的根源。

MyObject::MyObject( const MyObject& oCopy)
{
    *this = oCopy;//is this deep or shallow?
}
两者都不是。这是对分配操作员的呼叫。
由于您尚未完成对象的构造,这可能是不明智的(尽管完全正确)。但是,更传统的做法是根据复制构造函数定义赋值运算符(请参见复制和交换idium)

基本上可以,但通常分配的结果是不连续的。
但是如果你这样做的话,你需要将你的处理过程分开一点,以保证异常安全。它应该更像这样:

const MyObject& MyObject::operator=(const MyObject& oRhs)
{
    if( this == oRhs )
    {
        return *this;
    }
    // Stage 1:
    // Copy all members of oRhs that can throw during copy into temporaries.
    // That way if they do throw you have not destroyed this obbject.

    // Stage 2:
    // Copy anything that can **not** throw from oRhs into this object
    // Use swap on the temporaries to copy them into the object in an exception sage mannor.

    // Stage 3:
    // Free any resources.
    return *this;
}
当然,使用复制和交换idum有一种更简单的方法:

MyObject& MyObject::operator=(MyObject oRhs)  // use pass by value to get copy
{
    this.swap(oRhs);
    return *this;
}

void MyObject::swap(MyObject& oRhs)  throws()
{
    // Call swap on each member.
    return *this;
}
如果析构函数中没有什么要做的,不要声明它(除非它需要是虚拟的)

这里您声明的是一个指针(不是对象),因此不会调用构造函数(因为指针没有构造函数)

这里您正在调用new来创建对象。
你确定要这样做吗?必须销毁动态分配的对象;表面上通过删除,但更通常是C++中,在智能指针内包装指针,以确保所有者正确地自动销毁对象。
int main()
{ //^^^^   Note main() has a lower case m

    mpoOriginal = new MyObject();
    return DoSomething();
}
但由于您可能不想要动态对象。您需要的是当对象超出范围时被销毁的自动对象。另外,您可能不应该使用全局变量(将其作为参数传递,否则您的代码将使用与全局状态关联的副作用)

不需要调用new来创建副本,只需创建一个对象(传递要复制的对象)


操作符=(const MyObject&)
是什么样子的?您能否提供一个完整的可编译示例来演示这个问题?如果需要的话,消除“正在进行的大量工作”,这可能与问题有关,也可能与问题无关。谁继续投票不符合标准的问题?我一直在看。有人在尝试快速获取徽章吗?我添加了overator=,我很想发布所有代码,但我认为我的雇主不会高兴。再加上5000行,5000行用于
操作符=
!好悲伤。这就是你的问题所在。但是为了回答您最初的问题,您的复制构造函数具有赋值运算符的语义,因此要判断它是浅的还是深的,您需要查看赋值运算符代码。但我不认为这是你真正的问题,真正的问题是你有一个无法管理的混乱的类。但是,如果他说他有常量成员是正确的,那么编译器就不可能合成赋值运算符。这就是让我困惑的地方。根据给出的代码,MyObject的析构函数不会释放任何指针member。如果这是真的,那么更可能的是,“//很多事情在进行”位以某种方式使poCopied指针无效。@约翰:他说他在哪里有
const
成员?@Tomalak:他说得不准确,我在解释上面代码中的话“很多事情,包括const,但我没有看到任何指针”。当然我可能错了。@john:那是在ctor主体中,不是成员初始值设定项,所以我
const MyObject& MyObject::operator=(const MyObject& oRhs)
{
    if( this == oRhs )
    {
        return *this;
    }
    // Stage 1:
    // Copy all members of oRhs that can throw during copy into temporaries.
    // That way if they do throw you have not destroyed this obbject.

    // Stage 2:
    // Copy anything that can **not** throw from oRhs into this object
    // Use swap on the temporaries to copy them into the object in an exception sage mannor.

    // Stage 3:
    // Free any resources.
    return *this;
}
MyObject& MyObject::operator=(MyObject oRhs)  // use pass by value to get copy
{
    this.swap(oRhs);
    return *this;
}

void MyObject::swap(MyObject& oRhs)  throws()
{
    // Call swap on each member.
    return *this;
}
MyObject::~MyObject(){
    //there is nothing here
}
const MyObject * mpoOriginal;//this gets initialized in the constructor
int main()
{ //^^^^   Note main() has a lower case m

    mpoOriginal = new MyObject();
    return DoSomething();
}
int main()
{
     const MyObject  mpoOriginal;
     return DoSomething(mpoOriginal);
}
bool DoSomething(MyObject const& data)
{
    MyObject   poCopied (data);     //the copy

    //lots of stuff going on
    // No need to delete.
    // delete poCopied;//this causes the crash - can't step into using GDB
    // When it goes out of scope it is auto destroyed (as it is automatic).

    return true;
}