C++中typedef和using

一、typedef

typedef是C/C++语言中保留的关键字,用来定义一种数据类型的别名。

ypedef定义的类型的作用域只在该语句的作用域之内

typedef经常使用的场景包括以下几种:

  1. 指定一个简单的别名,避免了书写过长的类型名称
  2. 实现一种定长的类型,在跨平台编程的时候尤其重要
  3. 使用一种方便阅读的单词来作为别名,方便阅读代码

1.1 减少书写类型的长度

这一使用方式比较常见的就是在C语言中定义结构体,在C语言中定义结构体的方式如下:(包含3种)

///第一种方式
struct MyStruct {
    int data1;
    char data2;
};
//之后定义变量
struct MyStruct a, b;

///第二种方式(声明的同时定义)
struct MyStruct {
    int data1;
    char data2;
}a, b;

///第三种方式(不需要提供结构体名字,直接定义)
struct {
    int data1;
    char data2;
}a, b;

为了简化书写,可以使用typedef来简化(这种方式在Windows API中非常的常见,使用过Win32 API编程的读者应该深有体会),比如Windows定义四边形区域RECT结构的代码:

typedef struct _RECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT;

使用typedef之后,可以将上面的代码修改为:

///第一种情况
struct MyStruct {
    int data1;
    char data2;
};
typedef struct MyStruct newtype;
newtype a, b;

///第二种情况
typedef struct MyStruct {
    int data1;
    char data2;
} newtype;
newtype a, b;

///第三种情况
typedef struct {
    int data1;
    char data2;
} newtype;
newtype a, b;

需要注意的是上面描述的是C语言的使用方法,在C++中定义struct之后再次声明变量时,不需要使用struct关键字

1.2 实现一种定长的类型

在C/C++中并没有规定int类型的长度,因此在不同的机器上很有可能表示int类型变量所占用的字节数是不同的,这样有时候会带来一些问题。为了解决这些问题,很多时候可以定义一个固定大小的类型(比如32位的Int类型)Int32,用来表示固定长度的整型。这样在任意的机器上都可以使用这个Int32的类型,保证它的长度是固定的32位(至于它底层使用的真正类型,会根据具体机器上使用对应的类型),在OpenGL中就采用了这种方式,定义了许多固定大小的整型。

1.3 实现一种有意义可读的别名

例如下面这段代码,速度和分数都是使用int类型来表示,函数调用的时候传入的也是整型,把速度变量传入到原本接收成绩的参数,并不会有错误。

int current_speed ;
int high_score ;

void congratulate(int your_score) {
    if (your_score > high_score)
        ...
}

为了区别开这两种类型(只是从阅读代码者角度来看,对编译器来说二者并无不同),可以使用typedef来定义两个不同的别名:

typedef int km_per_hour ;
typedef int points ;

km_per_hour current_speed ; 
points high_score ; 

void congratulate(points your_score) {
    if (your_score > high_score)
        ...
}

这样代码阅读起来更加清晰一些。
另外需要注意的是:当使用typedef定义了points(km_per_hour)为int类型,在使用int类型定义的时候都可以使用这两个别名来替换,但并不是二者可以完全替换,当定义unsigned int等类型时,使用points(km_per_hour)替换int是错误的。

    unsigned int a;         // Okay
    unsigned km_per_hour b; // 编译报错
    long int c;             // Okay
    long km_per_hour d;     // 编译报错

二、C++11下新的选择(使用using定义别名)

C++11 中扩展了using的使用场景(C++11之前using主要用来引入命名空间名字 如:using namespace std;),可以使用using定义类型的别名:
使用语法如下:

using 别名 = xxx(类型);

通过语法可以看出,using声明别名的顺序和typedef是正好相反:typedef首先是类型,接着是别名,而using使用别名作为左侧的参数,之后才是右侧的类型,例如上面的类型定义:

    typedef int points;
    using points = int; //等价的写法

在定义诸如函数指针等类型时,使用using的方式更加自然和易读

typedef void (*FP) (int, const std::string&);
using FP = void (*) (int, const std::string&); //等价的using别名

另外using可以在模板别名中使用,但是typedef不可以

template <typename T>
using Vec = MyVector<T, MyAlloc<T>>;

// usage
Vec<int> vec;

若使用typedef的方式改写如下:

template <typename T>
typedef MyVector<T, MyAlloc<T>> Vec;

// usage
Vec<int> vec;

当你使用编译器编译的时候,将会得到类似:error: a typedef cannot be a template的错误信息。

那么,为什么typedef不可以呢?在 n1449 中提到过这样的话:”we specifically avoid the term “typedef template” and introduce the new syntax involving the pair “using” and “=” to help avoid confusion: we are not defining any types here, we are introducing a synonym (i.e. alias) for an abstraction of a type-id (i.e. type expression) involving template parameters.” 所以,我认为这其实是标准委员会他们的观点与选择,在C++11中,也是完全鼓励用using,而不用typedef的。

那么,如果我们想要用typedef做到这一点,应该怎么办呢?如Meyers所述以及一些STL的做法,那就是包装一层,如:

template <typename T>
struct Vec
{
  typedef MyVector<T, MyAlloc<T>> type;
};

// usage
Vec<int>::type vec;

正如你所看到的,这样是非常不漂亮的。而更糟糕的是,如果你想要把这样的类型用在模板类或者进行参数传递的时候,你需要使用typename强制指定这样的成员为类型,而不是说这样的::type是一个静态成员亦或者其它情况可以满足这样的语法,如:

template <typename T>
class Widget
{
  typename Vec<T>::type vec;
};

然而,如果是使用using语法的模板别名,你则完全避免了因为::type引起的问题,也就完全不需要typename来指定了。

template <typename T>
class Widget
{
  Vec<T> vec;
};

都会非常的自然,所以于此,非常推荐using,而非typedef。

归根到底就是一句话,在C++11中,请使用using,而非typedef


————————————————
原文链接:https://blog.csdn.net/csxiaoshui/article/details/78038799

 

  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++,使用`using`和`typedef`都可以用来创建类型别名。它们的作用是相同的,都用于给现有的类型起一个别名。然而,`using`语句更加灵活、易读,并且提供了更多功能。 使用`using`语句创建类型别名更加直观和易读。例如,可以使用以下方式创建一个函数指针的别名: ```cpp using FP = void (*)(int, const std::string&); ``` 这比使用`typedef`语句更加清晰和简洁: ```cpp typedef void (*FP) (int, const std::string&); ``` 此外,`using`语句在定义泛型别名时更加方便。在`typedef`的情况下,需要将声明包装在结构,而`using`语句不需要这样做。例如: ```cpp template<typename T> using Accounts = std::unordered_map<Student_ID, std::vector<T>>; ``` 而使用`typedef`的情况下需要这样声明: ```cpp template<typename T> struct Accounts { typedef std::unordered_map<Student_ID, std::vector<T>> type; }; ``` 总的来说,虽然`typedef`允许声明各种类型,如函数指针、数组指针等,但与C的`using`语句相比,使用它的过程较为冗长和复杂。此外,`typedef`允许一次声明多个类型,这与`using`语句不同。因此,在C++,更推荐使用`using`语句来创建类型别名。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C++typedefusing](https://blog.csdn.net/youtiao_hulatang/article/details/104775111)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [C++usingtypedef 的区别](https://blog.csdn.net/nnnnnnnnnmmmmm/article/details/126646221)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值