【问题标题】:How can I overload the operator& in C++如何在 C++ 中重载运算符&
【发布时间】:2013-04-23 12:27:14
【问题描述】:

如何在 C++ 中重载运算符&?我试过这个:

#ifndef OBJECT_H
#define OBJECT_H
#include<cstdlib>
#include<iostream>

namespace TestNS{

    class Object{
    private:
        int ptrCount;
    public: 
        Object(): ptrCount(1){           
            std::cout << "Object created." << std::endl;
        }
        void *operator new(size_t size);
        void operator delete(void *p);
        Object *operator& (Object obj);
    };

    void *Object::operator new(size_t size){            
            std::cout << "Pointer created through the 'new' operator." << std::endl; 
            return malloc(size);
        }

    void Object::operator delete(void *p){
            Object * x = (Object *) p;
            if (!x->ptrCount){
                free(x);
                std::cout << "Object erased." << std::endl;
            }
            else{
                std::cout << "Object NOT erased. The " << x->ptrCount << "references are exist." 
                    << std::endl;
            }
        }
    
    Object *Object::operator& (Object obj){
            ++(obj.ptrCount);
            std::cout << "Counter is increased." << std::endl;
            return &obj;
        }
}
#endif

主要功能:

#include<iostream>
#include"Object.h"

namespace AB = TestNS;

int main(int argc, char **argv){
    AB::Object obj1;
    AB::Object *ptrObj3 = &obj1; // the operator& wasn't called.
    AB::Object *ptrObj4 = &obj1; // the operator& wasn't called.

    AB::Object *obj2ptr = new AB::Object();
}

输出结果:

对象已创建。

通过'new'操作符创建的指针。

对象已创建。

我的 operator& 没有被调用。为什么?

【问题讨论】:

  • 试试AB::Object *ptrObj5 = obj1 &amp; obj1;,你就会知道为什么。
  • 我认为你在这里做的是一个非常糟糕的主意。用于引用计数的 operator& 会导致悲伤。
  • 因为它是一个不完整的解决方案。特别是如果您从运算符返回原始指针。至少,返回一些减少销毁引用计数的东西。但是重载地址操作符的问题是它使处理对象变得很烦人。另外,普通引用而不是指针呢?我只能说 Object& 或 = *somePointer,而你无法跟踪它。基本上,这个方案有很多漏洞可以通过,您将花费所有时间调试引用计数错误。
  • 首先,重载一元 &amp; 通常是个坏主意。如果必须,那么您的设计就有缺陷——&amp; 应该基于侵入式引用计数(std::enable_shared_from_this 或自定义解决方案)返回一个指向this 的智能指针。不要重载运算符newdelete,这不是这些重载的用途——相反,隐藏构造函数并提供static smart_ptr&lt;Object&gt; CreatePtr( Args&amp;&amp;... args ) 包装器。请注意,自动存储中或另一个非垃圾收集对象中不能存在垃圾收集对象,因此这种设计会导致性能下降。

标签: c++


【解决方案1】:

您当前正在重载二进制 &amp; 运算符(即按位与)。要重载一元 &amp; 运算符,您的函数不应接受任何参数。它适用的对象是this所指向的对象。

Object *Object::operator& (){
    ++(this->ptrCount);
    std::cout << "Counter is increased." << std::endl;
    return this;
}

【讨论】:

  • 另外,您可能需要一个 const 和一个非常量重载。这是非常量的,您还需要返回 const Object* 的 const 。
  • @sftrabbit, @Sebastian Redl 谢谢!
  • 除此之外,请注意重载operator&amp; 通常是个坏主意,并且您不能在标准容器内使用重载一元&amp; 的类型...
【解决方案2】:

sftrabbit answer 的语法是正确的,但请注意您对 newdelete 所做的操作是不一致的。

new 和 delete 运算符作用于原始内存,而不是构造对象。

当你做A* p = new A ...

  • operator new 被调用并且...
  • 对象A 的构造函数被调用返回的内存地址和...
  • 最后将地址转换成A*并给p

同样,当您执行delete p ...

  • A 析构函数被调用并且...
  • 将内存地址提供给operator delete 以返回给系统。

在这两种情况下,A 对象实例的状态(其成员的值)都是未定义的:

  • operator new 内,无论你做什么,都会被后续的构造函数调用覆盖。如果构造函数没有初始化某些东西,标准会说它的值是未定义的(并且不能与您在new 中设置的相同)。
  • operator delete 中,您所做的任何事情都是在一个已经死去的对象上完成的(而您在其中找到的东西并不被授予“最后的存活状态”。

在任何情况下,当你调用 delete 时,对象就会死掉。在operator delete(在销毁之后调用)期间,您不能“将其从死亡中拯救出来”。它的目的是放置墓碑,而不是复活尸体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多