非平凡的副本构造函数做什么? [英] What does a non-trivial copy constructor do?

查看:73
本文介绍了非平凡的副本构造函数做什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++中,如果未定义副本构造函数,则编译器将为您执行此操作.如果定义了一个,则编译器不会.编译器生成的副本构造函数可以是平凡的或不平凡的.在琐碎的复制构造函数中,它会执行成员级复制.就是这样.

In C++, if a copy constructor is not defined the compiler will do that for you. If one is defined, compiler would not. The compiler generated copy constructor can be trivial or non-trivial. In a trivial copy constructor it does a member-wise copy. That's it.

但是,如果有虚函数,则复制构造函数是不平凡的.它不能只是按位复制.

However, if there is a virtual function, the copy constructor is non-trivial. It cannot just to bit-wise copy.

这是我的程序.没有什么特别的.只是为了说明我的观点.

So here is my program. There is nothing special. Just to make my point..

#include<iostream>
using namespace std;

class baseClass
{
public:
    int var;
    int* varPtr;
    const float floatVar;
    int &intRefVar;

    baseClass(int value) : var(value), varPtr(&var), floatVar(value), intRefVar(var)
    {
        cout << "baseClass constructor" << endl;
    }

    baseClass(const baseClass& objToCopy) : var(objToCopy.var), varPtr(&var), floatVar(objToCopy.floatVar), intRefVar(var)
    {
        cout << "baseClass copy constructor" << endl;
    }

    virtual void func()
    {
        cout << "Just a virtual func." << endl;
    }
};

class derivedClass : public baseClass
{
public:
    derivedClass(int value) : baseClass(value)
    {
        cout << "derivedClass constructor" << endl;
    }

    derivedClass(const derivedClass& objToCopy) : baseClass(objToCopy)
    {
        cout << "derivedClass copy constructor" << endl;
    }

    virtual void func()
    {
        cout << "Just another virtual func." << endl;
    }
};


int main(int argc, char** argv)
{
    derivedClass derClassObj1(10);
    derivedClass derClassObj2(derClassObj1);
    return 0;
}

在此程序中,

  1. 我已经定义了一个复制构造函数
  2. 我有一个虚函数,所以复制构造函数很简单

这是我的问题:

  1. 由于vptr的存在,非平凡的副本构造函数与平凡的副本构造函数有何不同?
  2. 为什么无法复制vptr?如果两个对象的类型相同(继承中的级别相同),那么它们都可以指向同一vtable,不是吗?
  3. 既然我已经定义了自己的副本构造函数,那么编译器是否向我的副本构造函数添加"特殊指令以处理虚拟性?

干杯.

推荐答案

由于vptr的存在,非平凡的副本构造函数与平凡的副本构造函数有何不同?

How does a non-trivial copy constructor differ from a trivial one due to the presence of a vptr?

vptr不是从 source 对象复制的,而是必须初始化以指向 destination 类的虚拟表.因此,不可能从源到目标直接复制"memcpy".

The vptr is not copied from the source object, but has to be initialized to point to the virtual table of the destination class. Therefore, a straight "memcpy" copy from source to destination is not possible.

此外,请记住,严格要求不是拥有vptr,兼容的实现可以通过其他方式实现虚拟调度(我不知道那会是什么).虽然,对于AFAIK,所有实现都使用此机制.但是无论采用哪种方式选择执行操作,很明显,都会有某些信息,例如vptr,必须以某种方式设置,而该方式与直接的"memcpy"副本不兼容.

Also, keep in mind that having a vptr is not strictly a requirement, a compliant implementation could implement virtual dispatching some other way (I don't know what that would be though). Although, AFAIK, all implementations use this mechanism. But whichever way an implementation chooses to do things, it is clear that there will be some piece of information like a vptr that will have to be set in some way that is incompatible with a straight "memcpy" copy.

为什么不能复制vptr?如果两个对象的类型相同(继承中的级别相同),那么它们都可以指向同一vtable,不是吗?

Why cannot the vptr be copied? If both objects of same type (same level in the inheritance), they both can point to the same vtable, can they not?

这里的棘手问题是,您假设两个相同类型的对象".在一般情况下情况并非如此.源对象很可能属于其他派生类,因此具有不同的虚拟表指针.另一个(更罕见的)实际问题与交叉模块代码(位于不同的DLL/so文件或可执行文件中)有关,其中,相同类型的两个对象可能使用不同的虚拟表(例如,在某些情况下,某些极端情况或黑名单代码)这样就可以不破坏ODR(例如不同的模板实例化).

The sticky issue here is that assumption you made that "both objects of same type". This is not true in the general case. The source object could very well be of some other derived class and therefore have a different virtual table pointer. Another (more rare) practical issue has to do with cross-modular code (in different DLL/so files or executables), where two objects of the same type might use different virtual tables (e.g., there are some corner cases or hackish code in which this is possible without breaking ODR, like different template instantiations).

但是要点是,无法确保编译器可以确保对于复制构造函数的任何使用,只是从源对象复制vptr并期望它适用于目标对象是安全的.

But the point is that there is no way that the compiler can be assured that for any use of the copy-constructor it is safe to just copy the vptr from the source object and expect it to be appropriate for the destination object.

既然我已经定义了自己的副本构造函数,那么编译器是否向我的副本构造函数添加"特殊指令以处理虚拟性?

Since I have defined my own copy constructor, does the compiler 'add' special instructions to my copy constructor to handle the virtualness?

是的.是的我不记得确切的规范,但基本的要求是,当您到达构造函数的主体时,vptr(或用于动态调度的任何其他机制)将被初始化.实质上,这要求编译器在所有用户定义的构造函数中添加代码以隐式初始化vptr.

Yes. It does. I don't remember the exact specification, but basically the requirement is that by the time you hit the body of the constructor, the vptr (or whatever other mechanism used for dynamic dispatch) is initialized. That essentially requires the compiler to add code to implicitly initialize the vptr, in all user-defined constructors.

这篇关于非平凡的副本构造函数做什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆