C++ 重写C++;

C++ 重写C++;,c++,operator-overloading,C++,Operator Overloading,我的任务是实现一个重写=运算符的方法。我写了一些东西,但老实说,我不知道我在做什么。有人能解释一下这样做的意义吗(不是一般意义上的,我理解,但就在这种情况下,我有点困惑)?我的方法应该实现什么?在当前代码中,我的逻辑在哪里失败 scene.cpp:70: error: no match for ‘operator=’ in ‘*(((Image*)(((long unsigned int)i) * 80ul)) + newArray) = *(((Scene*)this)->Scene::

我的任务是实现一个重写=运算符的方法。我写了一些东西,但老实说,我不知道我在做什么。有人能解释一下这样做的意义吗(不是一般意义上的,我理解,但就在这种情况下,我有点困惑)?我的方法应该实现什么?在当前代码中,我的逻辑在哪里失败

scene.cpp:70: error: no match for ‘operator=’ in ‘*(((Image*)(((long unsigned int)i) * 80ul)) + newArray) = *(((Scene*)this)->Scene::images + ((Image**)(((long unsigned int)i) * 8ul)))’

重写运算符就像现在重载函数一样;您可以通过=op进行复制

Scene A; Scene B; A.do_things(); B = A; 场景A; 场景B; A.做事; B=A;
如果没有重载=运算符;B=A会使B成为指向与A相同的对象的指针(因为C中的类实例变量是指针)。

不太确定您希望它做什么。但是它有很多缺点

通常,operator=会复制原件,而不会对原件进行任何更改

这看起来像是要将图像的所有权从一个对象转移到另一个对象

删除*源是危险的,因为它不是/不应该是所有者。源可以很容易地成为堆栈变量

来源!=因此,将图像分配给源只会扼杀一切


将图像存储在向量中可以为您分配内存并复制所有图像。

您的代码有一些问题

  • 不要
    删除源代码
    ,您将其作为对const的引用传入,所以不要管它
  • 不要改变来源。这是常数,所以你不能
  • 不要将新内存分配给
    this->images
    而不首先删除[]个图像
  • 您首先需要理解引用和指针之间的区别
  • 您需要了解什么是
    const
  • 由于各种原因,您无法将
    图像
    分配给
    。一个是你不应该(不能)分配给
    源代码
    。另一个是,除非
    场景
    图像
    ,否则不能将
    图像
    分配给
    场景
    指针

  • 有一个实现非平凡赋值运算符的规范解决方案:

    Scene const & Scene::operator=(Scene s) { swap(s); return *this; }
    void Scene::swap(Scene & s) /* nothrow */ {
        Image *temp_images = images; images = s.images; s.images = temp_images;
        int temp_maximum = maximum; maximum = s.maximum; s.maximum = temp_maximum;
    }
    
    这是完全异常安全的,因为它依赖于复制构造函数在交换源(使用无抛出交换)以替换目标之前创建源的临时副本。如果拷贝的任何部分出错,源和目标都将保持原样

    它唯一没有做的就是优化自我分配。然而,在自我分配的情况下,它确实能正常工作,我通常不会去优化不应该发生的事情(在实践中,这种情况很少发生)

    另一种选择是使用更传统的参数类型:

    Scene const & Scene::operator=(Scene const & s) {
        Scene temp(s);
        swap(temp);
        return *this;
    }
    

    但是,除了更加冗长之外,这个版本的效率可能更低,因为它保证了复制,而如果传递给s的参数是右值,则传递值版本可能会省略复制。

    在管理内存的类中实现复制构造函数或赋值运算符是非常棘手的,并确保您的代码异常安全。异常安全意味着,如果在程序中的任何一点引发异常,则确保手动管理的内存仍然正确清理。出现了一些成语来帮助解决这个问题:

    RAII的基本租户是,如果您必须管理内存(最近经常没有),请将内存处理封装在一个对象中,该对象在构造时只分配一块内存,在销毁时释放该内存

    复制和交换是在必须处理内存分配时实现非平凡赋值运算符的特定指导。这正是您试图解决的问题

    我建议您在继续编写管理内存的代码之前,先仔细阅读这两方面的内容,否则您可能会在试图消除所有bug时大发雷霆

    自己实现习惯用法的另一种方法是依靠
    std::vector
    tr1::shared\u ptr
    等代码来为您进行内存管理。许多知道C++和内存管理古怪的人都经常使用这两种方法。您通常可以仅凭这些就成功。

    您的(内部)代码在英语中的作用:

    //allocate new memory and copy
    images = new Image*[source.maximum];
    
    这将
    images
    设置为新分配的
    源的数组。最大
    未初始化
    images
    指针。任何
    图像
    指向的内容都将丢失

        Scene(source);
    
    这将创建一个新的临时
    场景
    对象,然后将其丢弃。它不会在此
    上“重新调用”构造函数

        //deallocate old memory
        delete *source;
    
    如果有效,这将取消引用
    source
    (这是一个
    const场景&
    ,因此只有在定义了
    T*Scene::operator*(void)
    时才有效,其中
    T
    是某种类型)并删除指向
    T
    的对象

        //assign
        source=images;
    
    这会尝试将
    图像
    复制到
    ,这不应该发生,因为
    常量
    。一旦创建,引用就不能更改为引用其他对象

        this->maximum=images.maximum;
    
    这不管用<代码>图像
    是一个
    图像**
    ,它没有
    最大值
    字段。另外,
    this->
    是冗余的

    更新:关于新版本:

    首先,你不需要到处说
    this->

    for (int i=0;i<source.maximum;i++)
        this->images[i]=source->images[i];
    
    这假设您有一个用于
    Image
    Image::Image(const Image&);
    )的复制构造函数

    最后,
    Scene
    应该有一个与此类似的复制构造函数,只是它不需要删除旧的内容。如果不复制图像,请使用:

    Scene::Scene(const Scene& original): maximum(original.maximum)
    {
        images = new Image*[maximum];
        for(size_t i = 0; i < maximum; i++)
            images[i] = source.images[i];
    }
    
    Scene::Scene(const Scene& original): maximum(original.maximum)
    {
        images = new Image*[maximum];
        for(size_t i = 0; i < maximum; i++)
            images[i] = new Image(*(source.images[i]));
    }
    
    Scene::Scene(const Scene&original):最大值(original.max)
    {
    图像=新图像*[最大值];
    对于(尺寸i=0;i<最大值;i++)
    images[i]=source.images[i];
    }
    
    Scene::Scene(const Scene& original): maximum(original.maximum)
    {
        images = new Image*[maximum];
        for(size_t i = 0; i < maximum; i++)
            images[i] = new Image(*(source.images[i]));
    }