int operator *() 和operator int*()的区别

NULL 0 和 c ++ 11 nullptr

简单描述就是因为c语言有隐士类型转换所以(void*)可以转化为任意一种指针可是c++并不提供这种方式所以在一些赋值操作中要强转,为了兼容和使用上的一致就定义了

c++ NULL 是0 但是这个0又会产生和数字0的奇异性造成使用上的麻烦,所以产生了一个新的机制c++11提供的nullptr 具体定义如下图

C++运算符重载 "int operator*() {}" 与 "operator int*(){}"的区别?

在阅读libc++中 nullptr_t源码的时候,遇到了下面的关于运算符重载的用法。
 template <class _Tp>
        _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR
        operator _Tp* () const {return 0;}

_Tp 应该是一种类型,但是我从没有见到过这种使用方式,所以写一段代码实验一下。示例代码如下:

#include <iostream>
using namespace std;
class Base
{
    int mem;
public:
    Base() : mem(0) {}
    int operator*() { return 1; };
    operator int*() { return 0; }
};
int main()
{
    Base b;
    std::cout << "*b: " << *b << std::endl;
    std::cout << "b: " << b << std::endl;
    return 0;
}

上面的输出结果如下:

$ g++ test.cpp
// ---------- ouput --------
$ *b: 1
$ b: 0

环境:ubuntu14.04 g++4.8.4

从上面的输出结果可以看到 *b 调用的是 "int operator*() { return 0; }",也就是运算符 * 的重载形式;而 b 调用的是 "operator int*() { return 0; }"。将该段代码的AST打印出来如下:

clang -Xclang -ast-dump test.cpp
// ---------AST---------
CXXConversionDecl 0xa745170 <line:13:2, line:16:2> line:13:2 used operator int * 'int *(void)'
| | `-CompoundStmt 0xa7452d8 <line:14:2, line:16:2>
| |   `-ReturnStmt 0xa7452c8 <line:15:3, col:10>
| |     `-ImplicitCastExpr 0xa7452b8 <col:10> 'int *' <NullToPointer>

查阅Clang源码,查找CXXConversionDecl的定义,注释如下:

/// \brief Represents a C++ conversion function within a class.
2454	///
2455	/// For example:
2456	///
2457	/// \code
2458	/// class X {
2459	/// public:
2460	///   operator bool();
2461	/// };
2462	/// \endcode
2463	class CXXConversionDecl : public CXXMethodDecl {
2464	  void anchor() override;
2465	  /// Whether this conversion function declaration is marked
2466	  /// "explicit", meaning that it can only be applied when the user
2467	  /// explicitly wrote a cast. This is a C++11 feature.
          /// ...
        }

从上面的代码中看到 operator int*() {} 是一种类型转换运算符重载(type-cast operator)形式,将类型 Base 的对象转换为 int* 类型。可是刚开始我为什么没有看出来这是一种类型转换运算符重载呢?

估计是由于在日常编码过程中我见到的大抵都是如下这种形式:

class MyInt
{
    int num;
public:
    MyInt(int num) : num(num) {}
    // 这里的类型都很简单
    operator int() { return num; }
};

但是在这个示例中出现了复合类型(compound type - (that is, array, function, object pointer, function pointer, member object pointer, member function pointer, reference, class, union, or enumeration, including any cv-qualified variants),所以有些违背直觉。其实类型转换运算的目的类型也可以很复杂,例如 operator const int*&() 等等。

另外这里的问题不仅仅在于类型转换的目的类型比较复杂,还在于类型转换运算符(type-cast operator)本身就比较特殊,"The type-cast operator uses a particular syntax: it uses the operator keyword followed by the destination type and an empty set of parentheses." ,使用了operator运算符,但是不像 + 或者 *,会出现在函数声明中,例如

> int operator*() { return 0; }

如果类型运算符重载使用下面这种形式的话,估计更易读一些。

> int* operator type_cast() { return 0; }

可惜,类型转换运算符的重载偷了个懒,直接将前面的 int* 挪到了后面,成了 operator int*() {} ,所以就带来了些困扰。

对于自定义类型来说,大致有三种隐式类型转换的方式。

  • Single-argument constructors: allow implicit conversion from a particular type to initialize an object.
  • Assignment operator: allow implicit conversion from a particular type on assignments.
  • Type-cast operator: allow implicit conversion to a particular type

注:上述描述来自Type conversions,下面的示例代码也恬不知耻的抄袭了此处

// implicit conversion of classes:
#include <iostream>
using namespace std;

class A {};

class B {
public:
  // conversion from A (constructor):
  B (const A& x) {}
  // conversion from A (assignment):
  B& operator= (const A& x) {return *this;}
  // conversion to A (type-cast operator)
  operator A() {return A();}
};

int main ()
{
  A foo;
  B bar = foo;    // calls constructor
  bar = foo;      // calls assignment
  foo = bar;      // calls type-cast operator
  return 0;
}

三种方式都可以在大部分场景下正常使用,但还是推荐在第一种和第三种前面加上 explicit 关键字,这样就要求程序员显示使用static_cast<>来进行类型的转换,方便阅读,例如"explicit operator A() { return A(); }"

注:类型转换运算符是有返回值的,返回类型由 operator 后面的目的类型标明。


https://zhuanlan.zhihu.com/p/22502093 转载来自

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值