什么是C ++复制构造函数的所有大惊小怪? [英] What's all the fuss about C++ copy constructors?

查看:117
本文介绍了什么是C ++复制构造函数的所有大惊小怪?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

何时必须使用复制构造函数?


为什么C ++复制构造函数如此重要?我刚刚了解他们,我不太明白他们是什么大惊小怪。看起来你应该总是为你的类写一个复制构造函数,如果你使用指针,但为什么?



谢谢Boda Cydo。



更明确地声明例如:

  class P2d 
{
public:
double x,y;
P2d(double x,double y):x(x),y​​(y)
{}
};

C ++编译器自动完成您的代码

  class P2d 
{
public:
double x,y;
P2d(double x,double y):x(x),y​​(y)
{}

P2d(const P2d& other) ,y(other.y)
{}

P2d& operator =(const P2d& other)
{
x = other.x;
y = other.y;
return * this;
}
};这些自动生成的拷贝构造函数和赋值运算符是否对您的类是否正确?


$ b <在许多情况下是...但当然可能是那些实现完全错误。例如,当你有指针包含在你的对象中,然后只是复制指针,当你想复制的对象是不正确的事情做。



你必须明白,C ++做了很多对象的副本,你必须知道它将为你定义的类做什么类型的副本。如果自动生成的副本不是你需要的,那么你必须提供自己的实现,或者你必须告诉编译器该副本应该禁止你的类。



你可以通过声明一个私有复制构造函数和赋值运算符,以及不提供实现来防止编译器进行复制。因为这些是 private 函数,任何将要使用它们的外部代码都会收到编译器错误,并且因为你声明了它们,但是没有实现它们,如果错误地结束,你会得到一个链接错误



例如:

  class Window 
{
public:
WindowType t;
Window * parent,
* prev_in_parent,* next_in_parent,
* first_children,* last_children;
Window(Window * parent,WindowType t);
〜Window();

private:
// TABOO! - 声明但未实现
Window(const Window&);
窗口& operator =(const Window&);
};

如果最后一个部分似乎荒谬(如何在错误的实施中复制)在C ++中非常容易错误地创建额外的副本,因为语言是围绕复制的概念构建的。



一个黄金规则是,如果你的类有一个析构函数(因为它需要做一些清理),然后最可能是一个成员一个成员副本不是正确的事情做...以及如果你有特殊的逻辑来做一个副本构建,那么类似的逻辑可能需要也在分配(反之亦然)。因此,被称为三巨头的规则声明,您的类没有自定义析构函数,没有复制构造函数,没有赋值运算符,或者您的类应该具有全部三个。



这个规则是非常重要的,例如,如果对于任何特殊情况,你最终只需要一个只需要一个析构函数的类(我不能认为一个合理的情况...但让我们说你发现一个),那么请记住添加作为一个注释,你想到它,你知道隐式生成的复制构造函数和赋值运算符是确定。
如果你不添加关于其他两个的注释,谁将读取代码将认为你只是忘了他们。


Possible Duplicate:
When do we have to use copy constructors?

Why exactly are C++ copy constructors so important? I just learned about them and I don't quite see what is the fuss about them. It seems you should always write a copy constructor for your classes if you use pointers, but why?

Thanks, Boda Cydo.

解决方案

Copy constructor and assignment operators are very important in C++ because the language has "copy semantic", that is to say when you pass a parameter or store a value in a container a copy of the object is passed or stored. How can C++ make a copy or perform an assignment on an object ? For native types it knows by itself, for user defined types instead it automatically generates a member-by-member copy construction or assignment.

More explicitly if you declare for example:

class P2d
{
    public:
        double x, y;
        P2d(double x, double y) : x(x), y(y)
        { }
};

the C++ compiler automatically completes your code to

class P2d
{
    public:
        double x, y;
        P2d(double x, double y) : x(x), y(y)
        { }

        P2d(const P2d& other) : x(other.x), y(other.y)
        { }

        P2d& operator=(const P2d& other)
        {
            x = other.x;
            y = other.y;
            return *this;
        }
};

Are these automatically generated copy constructor and assignment operators correct for your class? In many cases yes... but of course may be those implementations are totally wrong. Quite often for example when you have pointers contained inside your objects then just copying the pointer when you want to make a copy of the object is not the right thing to do.

You must understand that C++ does a lot of copies of objects, and you must understand what type of copy it will do for classes you defined. If the automatically generated copy is not what you need then you must either provide your own implementation, or you must tell the compiler that copy should be forbidden for your class.

You can prevent the compiler from making copies by declaring a private copy constructor and assignment operator, and by not providing an implementation. Because those are private functions any external code that is going to use them will get a compiler error, and because you declared them but you didn't implement them you will get a link error if by mistake you end up making copies inside the class implementation.

For example:

class Window
{
    public:
        WindowType t;
        Window *parent,
               *prev_in_parent, *next_in_parent,
               *first_children, *last_children;
        Window(Window *parent, WindowType t);
        ~Window();

    private:
        // TABOO! - declared but not implemented
        Window(const Window&);
        Window& operator=(const Window&);
};

If the last part seems absurd (how can you make copies in the implementation by mistake) please note that in C++ is very very easy to make extra copies by mistake because the language has been built around the concept of copying things around.

A golden rule is that if your class has a destructor (because it needs to do some cleanup) then most probably a member-by-member copy is not the right thing to do... and also if you have special logic to do a copy construction then a similar logic is probably needed also in assignment (and vice versa). So the rule, known as Big Three, states that either your class has no custom destructor, no copy constructor, no assignment operator or your class should have all three of them.

This rule is so important that for example if for any special case you end up with a class that just needs a destructor (I can't think a sensible case... but let's just say you found one) then please remember to add as a comment that you thought about it and you know that the implicitly generated copy constructor and assignment operators are ok. If you don't add a note about the other two, who will read the code will think that you simply forgot about them.

这篇关于什么是C ++复制构造函数的所有大惊小怪?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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