我什么时候应该在c++中使用typedef ?

时间:2022-09-10 23:31:38

In my years of C++ (MFC) programming in I never felt the need to use typedef, so I don't really know what is it used for. Where should I use it? Are there any real situations where the use of typedef is preferred? Or is this really more a C-specific keyword?

在我的c++ (MFC)编程生涯中,我从来没有觉得需要使用typedef,所以我真的不知道它的用途是什么。我应该在哪里使用它?是否存在使用typedef的实际情况?或者这真的是一个特定于c的关键字吗?

12 个解决方案

#1


76  

Template Metaprogramming

typedef is necessary for many template metaprogramming tasks -- whenever a class is treated as a "compile-time type function", a typedef is used as a "compile-time type value" to obtain the resulting type. E.g. consider a simple metafunction for converting a pointer type to its base type:

对于许多模板元编程任务来说,类型定义都是必需的——每当类被视为“编译时类型函数”时,类型定义就被用作“编译时类型值”,以获得结果类型。例如,考虑一个简单的元函数,将指针类型转换为它的基类型:

template<typename T>
struct strip_pointer_from;

template<typename T>
struct strip_pointer_from<T*> {   // Partial specialisation for pointer types
    typedef T type;
};

Example: the type expression strip_pointer_from<double*>::type evaluates to double. Note that template metaprogramming is not commonly used outside of library development.

示例:类型表达式strip_pointer_from :::类型计算值为double。注意,模板元编程在库开发之外通常不使用。 *>

Simplifying Function Pointer Types

typedef is helpful for giving a short, sharp alias to complicated function pointer types:

typedef有助于为复杂的函数指针类型提供一个短而尖锐的别名:

typedef int (*my_callback_function_type)(int, double, std::string);

void RegisterCallback(my_callback_function_type fn) {
    ...
}

#2


28  

In Bjarne's book he states that you can use typedef to deal with portability problems between systems that have different integer sizes. (this is a paraphrase)

在Bjarne的书中,他指出您可以使用typedef来处理具有不同整数大小的系统之间的可移植性问题。(这是一个改写)

On a machine where sizeof(int) is 4 you can

在sizeof(int)是4的机器上你可以

typedef int int32;

Then use int32 everywhere in your code. When you move to an implementation of C++ where sizeof(int) is 2, then you can just change the typdef

然后在代码中使用int32。当您移动到c++的实现,其中sizeof(int)是2,那么您可以更改类型定义

typedef long int32;

and your program will still work on the new implementation.

你的程序仍然会在新的实现中工作。

#3


16  

Just to provide some examples for the things said: STL containers.

为STL容器提供一些例子。

 typedef std::map<int,Froboz> tFrobozMap;
 tFrobozMap frobozzes; 
 ...
 for(tFrobozMap::iterator it=frobozzes.begin(); it!=map.end(); ++it)
 {
     ...
 }

It is not unusual to even use typedefs like

甚至使用typedefs也是很正常的。

typedef tFrobozMap::iterator tFrobozMapIter;
typedef tFrobozMap::const_iterator tFrobozMapCIter;

Another example: using shared pointers:

另一个例子:使用共享指针:

class Froboz;
typedef boost::shared_ptr<Froboz> FrobozPtr;

[update] As per comment - where to put them?

[更新]每条评论——把它们放在哪里?

The last example - using shared_ptr - is easy: are true header material - or at least a forward header. You do need the forward declaration for shared_ptr anyway, and one of its declared advantages is that it's safe to use with a forward decl.

最后一个例子——使用shared_ptr——很简单:是真正的头信息——或者至少是一个转发头信息。无论如何,您确实需要shared_ptr的forward声明,它声明的优点之一是使用forward decl是安全的。

Put it another way: If there is a shared_ptr you probably should use the type only through a shared_ptr, so separating the declarations doesn't make much sense.

换句话说:如果存在shared_ptr,那么您可能应该只通过shared_ptr使用该类型,因此分离声明没有多大意义。

(Yes, xyzfwd.h is a pain. I'd use them only in hotspots - knowing that hotspots are hard to identify. Blame the C++ compile+link model...)

(是的,xyzfwd。h是一个痛苦。我只在热点地区使用它们——知道热点很难识别。归咎于c++编译+链接模型…)

Container typedefs I usually use where the container variable is declared - e.g. locally for a local var, as class members when the actual container instance is a class member. This works well if the actual container type is an implementation detail - causing no additional dependency.

我通常在声明容器变量的地方使用容器类型defs—例如,本地的var,当实际的容器实例是类成员时,它作为类成员。如果实际的容器类型是一个实现细节,这将很好地工作——不会产生额外的依赖性。

If they become part of a particular interface, they are declared together with the interface they are used with, e.g.

如果它们成为特定接口的一部分,它们将与它们所使用的接口一起声明,例如。

// FrobozMangler.h
#include "Froboz.h"
typedef std::map<int, Froboz> tFrobozMap;
void Mangle(tFrobozMap const & frobozzes); 

That gets problematic when the type is a binding element between different interfaces - i.e. the same type is needed by multiple headers. Some solutions:

当类型是不同接口之间的绑定元素时,就会出现问题——即多个头需要相同的类型。一些解决方案:

  • declare it together with the contained type (suitable for containers that are frequently used for this type)
  • 与所包含的类型一起声明它(适用于经常用于此类型的容器)
  • move them to a separate header
  • 将它们移动到一个单独的头部
  • move to a separate header, and make it a data class where the actual container is an implementation detail again
  • 移动到一个单独的头,并使它成为一个数据类,其中实际的容器又是一个实现细节。

I agree that the two latter aren't that great, I'd use them only when I get into trouble (not proactively).

我同意后者不是很好,我只有在遇到麻烦时才会使用它们(而不是主动)。

#4


15  

use with function pointer

使用函数指针

Hide Function Pointer Declarations With a typedef

用类型定义隐藏函数指针声明

void (*p[10]) (void (*)() );

Only few programmers can tell that p is an "array of 10 pointers to a function returning void and taking a pointer to another function that returns void and takes no arguments." The cumbersome syntax is nearly indecipherable. However, you can simplify it considerably by using typedef declarations. First, declare a typedef for "pointer to a function returning void and taking no arguments" as follows:

只有很少的程序员知道p是一个“10个指针的数组,指向一个返回void的函数,指向另一个返回void且不带参数的函数。”复杂的语法几乎难以理解。但是,您可以通过使用typedef声明来大大简化它。首先,声明“返回void且不带参数的函数指针”的类型def如下:

  typedef void (*pfv)();

Next, declare another typedef for "pointer to a function returning void and taking a pfv" based on the typedef we previously declared:

接下来,声明另一个typedef,用于“指向返回void的函数的指针”,并基于我们之前声明的typedef来进行“pfv”:

 typedef void (*pf_taking_pfv) (pfv);

Now that we have created the pf_taking_pfv typedef as a synonym for the unwieldy "pointer to a function returning void and taking a pfv", declaring an array of 10 such pointers is a breeze:

现在,我们已经创建了pf_taking_pfv类型定义,作为“指向函数返回void和使用pfv的指针”的同义词,声明了10个这样的指针的数组是一种轻松:

  pf_taking_pfv p[10];

from

#5


5  

typedef is useful in a lot of situations.

定义类型在很多情况下都很有用。

Basically it allows you to create an alias for a type. When/if you have to change the type, the rest of the code could be unchanged (this depends on the code, of course). For example let's say you want to iter on a c++ vector

基本上,它允许您为类型创建别名。当/如果必须更改类型,则代码的其余部分可以保持不变(当然,这取决于代码)。例如,假设你想对一个c++向量进行iter

vector<int> v;

...

for(vector<int>::const_iterator i = v->begin(); i != v.end(); i++) {

// Stuff here

}

In the future you may think to change the vector with a list, because the type of operations you have to do on it. Without typedef you have to change ALL occurrences of vector within your code. But if you write something like this:

将来你可能会想用一个列表来改变矢量,因为你要对它做的操作的类型。没有typedef,您必须更改代码中出现的所有向量。但是如果你这样写:

typedef vector<int> my_vect;

my_vect v;

...

for(my_vect::const_iterator i = v->begin(); i != v.end(); i++) {

// Stuff here

}

Now you just have to change one row of code (i.e from "typedef vector<int> my_vect" to "typedef list<int> my_vect") and everything works.

现在你只需要修改一行代码(i)。e从“typedef vector my_vect”到“typedef list my_vect”),一切正常。

typedef also saves you time when you have complex data structures which are very long to write (and difficult to read)

当您拥有复杂的数据结构时,typedef还可以节省您的时间,这些数据结构非常长(而且难于阅读)

#6


5  

One good reason to use typedef is if the type of something may change. For example, let's say that for now, 16-bit ints are fine for indexing some dataset because for the foreseeable future, you'll have less than 65535 items, and that space constraints are significant or you need good cache performance. However, on the off chance that you need to use your program on a dataset with more than 65535 items, you want to be able to easily switch to a wider integer. Use a typedef, and you only have to change this in one place.

使用typedef的一个很好的理由是如果某些东西的类型可能会改变。例如,假设目前16位的int对于某些数据集来说是可以的,因为在可预见的将来,您将拥有少于65535个项,并且空间约束非常重要,或者您需要良好的缓存性能。但是,如果您需要在包含超过65535项的数据集中使用程序,那么您希望能够轻松地切换到更大的整数。使用类型定义,您只需在一个地方更改它。

#7


4  

typedef allows to not only have an alias for complex types, but gives you an natural place to document a type. I sometimes use it for documentational purposes.

typedef不仅可以为复杂类型提供别名,还可以为您提供一个记录类型的自然位置。我有时用它来做记录。

There are also times when I use an array of bytes. Now, an array of bytes could mean a lot of things. typedef makes it handy to define my byte array as "hash32", or "fileContent" to make my code more readable.

有时我使用字节数组。现在,一个字节数组意味着很多事情。typedef可以方便地将字节数组定义为“hash32”或“fileContent”,以便使代码更具可读性。

#8


2  

Real-world uses of typedef:

实际使用的类型:

  • providing friendly aliases for long-winded templated types
  • 为冗长的模板类型提供友好的别名
  • providing friendly aliases for function pointer types
  • 为函数指针类型提供友好的别名
  • providing local labels for types, e.g.:

    为类型提供本地标签,例如:

    template<class _T> class A
    {
        typedef _T T;
    };
    
    template<class _T> class B
    {
        void doStuff( _T::T _value );
    };
    

#9


2  

There is one another use case to use typedef is when we want to enable a kind of Container Independent code (but not exactly!)

使用typedef还有另外一个用例,当我们想要启用某种容器独立的代码时(但不是完全如此!)

Let us say you have class:

假设你有课:

Class CustomerList{

public:
    //some function
private:
    typedef list<Customer> CustomerContainer;
    typedef CustomerContainer::iterator Cciterator;
};

The above code encapsulates the internal container implementation using typedef and even if in future the list container needs to changed to vector or deque still the user of the CustomerList class doesn't need to worry about exact container implementation.

上面的代码使用typedef封装内部容器实现,即使将来列表容器需要更改为vector或deque, CustomerList类的用户也不需要担心确切的容器实现。

Hence, the typedef encapsulates and somewhat help us to write Container Independent code

因此,typedef封装并在一定程度上帮助我们编写容器独立的代码

#10


0  

Whenever it makes the source clearer or better to read.

无论何时它使源文件更清晰或更好阅读。

I use kind of typedef in C# for generics/templates. A "NodeMapping" is just better to read/use and understand then a lot of "Dictionary<string, XmlNode>". IMHO. So I'd recommend it for templates.

我在c#中对泛型/模板使用某种类型定义。“NodeMapping”最好是读/使用,然后理解很多“字典 ”。恕我直言。所以我推荐它作为模板。 ,>

#11


0  

Typedef allows flexibility in your class. When you want to change the data type in the program, you do not need to change multiple locations but just need to change one occurrence.

Typedef允许您的类具有灵活性。当您想要更改程序中的数据类型时,您不需要更改多个位置,而只需更改一个事件。

typedef <datatype example  int or double> value_type

you can give nay name instead of value_type, but value_type is normally the standard name.

可以用nay型代替value_type,但value_type通常是标准名。

So u can use typedef like

所以你可以用类型定义

value_type i=0;     //same as a int or double i=0; 

#12


-1  

... and you Don't Need a Typedef for an enum or a struct.

…您不需要为enum或struct使用类型定义。

Or do you?

还是你?

typedef enum { c1, c2 } tMyEnum;
typedef struct { int i; double d; } tMyStruct;

can be better written as

可以写成更好的形式吗

enum tMyEnum { c1, c2 }
struct  tMyStruct { int i; double d; };

Is that correct? What about C?

那是正确的吗?C呢?

#1


76  

Template Metaprogramming

typedef is necessary for many template metaprogramming tasks -- whenever a class is treated as a "compile-time type function", a typedef is used as a "compile-time type value" to obtain the resulting type. E.g. consider a simple metafunction for converting a pointer type to its base type:

对于许多模板元编程任务来说,类型定义都是必需的——每当类被视为“编译时类型函数”时,类型定义就被用作“编译时类型值”,以获得结果类型。例如,考虑一个简单的元函数,将指针类型转换为它的基类型:

template<typename T>
struct strip_pointer_from;

template<typename T>
struct strip_pointer_from<T*> {   // Partial specialisation for pointer types
    typedef T type;
};

Example: the type expression strip_pointer_from<double*>::type evaluates to double. Note that template metaprogramming is not commonly used outside of library development.

示例:类型表达式strip_pointer_from :::类型计算值为double。注意,模板元编程在库开发之外通常不使用。 *>

Simplifying Function Pointer Types

typedef is helpful for giving a short, sharp alias to complicated function pointer types:

typedef有助于为复杂的函数指针类型提供一个短而尖锐的别名:

typedef int (*my_callback_function_type)(int, double, std::string);

void RegisterCallback(my_callback_function_type fn) {
    ...
}

#2


28  

In Bjarne's book he states that you can use typedef to deal with portability problems between systems that have different integer sizes. (this is a paraphrase)

在Bjarne的书中,他指出您可以使用typedef来处理具有不同整数大小的系统之间的可移植性问题。(这是一个改写)

On a machine where sizeof(int) is 4 you can

在sizeof(int)是4的机器上你可以

typedef int int32;

Then use int32 everywhere in your code. When you move to an implementation of C++ where sizeof(int) is 2, then you can just change the typdef

然后在代码中使用int32。当您移动到c++的实现,其中sizeof(int)是2,那么您可以更改类型定义

typedef long int32;

and your program will still work on the new implementation.

你的程序仍然会在新的实现中工作。

#3


16  

Just to provide some examples for the things said: STL containers.

为STL容器提供一些例子。

 typedef std::map<int,Froboz> tFrobozMap;
 tFrobozMap frobozzes; 
 ...
 for(tFrobozMap::iterator it=frobozzes.begin(); it!=map.end(); ++it)
 {
     ...
 }

It is not unusual to even use typedefs like

甚至使用typedefs也是很正常的。

typedef tFrobozMap::iterator tFrobozMapIter;
typedef tFrobozMap::const_iterator tFrobozMapCIter;

Another example: using shared pointers:

另一个例子:使用共享指针:

class Froboz;
typedef boost::shared_ptr<Froboz> FrobozPtr;

[update] As per comment - where to put them?

[更新]每条评论——把它们放在哪里?

The last example - using shared_ptr - is easy: are true header material - or at least a forward header. You do need the forward declaration for shared_ptr anyway, and one of its declared advantages is that it's safe to use with a forward decl.

最后一个例子——使用shared_ptr——很简单:是真正的头信息——或者至少是一个转发头信息。无论如何,您确实需要shared_ptr的forward声明,它声明的优点之一是使用forward decl是安全的。

Put it another way: If there is a shared_ptr you probably should use the type only through a shared_ptr, so separating the declarations doesn't make much sense.

换句话说:如果存在shared_ptr,那么您可能应该只通过shared_ptr使用该类型,因此分离声明没有多大意义。

(Yes, xyzfwd.h is a pain. I'd use them only in hotspots - knowing that hotspots are hard to identify. Blame the C++ compile+link model...)

(是的,xyzfwd。h是一个痛苦。我只在热点地区使用它们——知道热点很难识别。归咎于c++编译+链接模型…)

Container typedefs I usually use where the container variable is declared - e.g. locally for a local var, as class members when the actual container instance is a class member. This works well if the actual container type is an implementation detail - causing no additional dependency.

我通常在声明容器变量的地方使用容器类型defs—例如,本地的var,当实际的容器实例是类成员时,它作为类成员。如果实际的容器类型是一个实现细节,这将很好地工作——不会产生额外的依赖性。

If they become part of a particular interface, they are declared together with the interface they are used with, e.g.

如果它们成为特定接口的一部分,它们将与它们所使用的接口一起声明,例如。

// FrobozMangler.h
#include "Froboz.h"
typedef std::map<int, Froboz> tFrobozMap;
void Mangle(tFrobozMap const & frobozzes); 

That gets problematic when the type is a binding element between different interfaces - i.e. the same type is needed by multiple headers. Some solutions:

当类型是不同接口之间的绑定元素时,就会出现问题——即多个头需要相同的类型。一些解决方案:

  • declare it together with the contained type (suitable for containers that are frequently used for this type)
  • 与所包含的类型一起声明它(适用于经常用于此类型的容器)
  • move them to a separate header
  • 将它们移动到一个单独的头部
  • move to a separate header, and make it a data class where the actual container is an implementation detail again
  • 移动到一个单独的头,并使它成为一个数据类,其中实际的容器又是一个实现细节。

I agree that the two latter aren't that great, I'd use them only when I get into trouble (not proactively).

我同意后者不是很好,我只有在遇到麻烦时才会使用它们(而不是主动)。

#4


15  

use with function pointer

使用函数指针

Hide Function Pointer Declarations With a typedef

用类型定义隐藏函数指针声明

void (*p[10]) (void (*)() );

Only few programmers can tell that p is an "array of 10 pointers to a function returning void and taking a pointer to another function that returns void and takes no arguments." The cumbersome syntax is nearly indecipherable. However, you can simplify it considerably by using typedef declarations. First, declare a typedef for "pointer to a function returning void and taking no arguments" as follows:

只有很少的程序员知道p是一个“10个指针的数组,指向一个返回void的函数,指向另一个返回void且不带参数的函数。”复杂的语法几乎难以理解。但是,您可以通过使用typedef声明来大大简化它。首先,声明“返回void且不带参数的函数指针”的类型def如下:

  typedef void (*pfv)();

Next, declare another typedef for "pointer to a function returning void and taking a pfv" based on the typedef we previously declared:

接下来,声明另一个typedef,用于“指向返回void的函数的指针”,并基于我们之前声明的typedef来进行“pfv”:

 typedef void (*pf_taking_pfv) (pfv);

Now that we have created the pf_taking_pfv typedef as a synonym for the unwieldy "pointer to a function returning void and taking a pfv", declaring an array of 10 such pointers is a breeze:

现在,我们已经创建了pf_taking_pfv类型定义,作为“指向函数返回void和使用pfv的指针”的同义词,声明了10个这样的指针的数组是一种轻松:

  pf_taking_pfv p[10];

from

#5


5  

typedef is useful in a lot of situations.

定义类型在很多情况下都很有用。

Basically it allows you to create an alias for a type. When/if you have to change the type, the rest of the code could be unchanged (this depends on the code, of course). For example let's say you want to iter on a c++ vector

基本上,它允许您为类型创建别名。当/如果必须更改类型,则代码的其余部分可以保持不变(当然,这取决于代码)。例如,假设你想对一个c++向量进行iter

vector<int> v;

...

for(vector<int>::const_iterator i = v->begin(); i != v.end(); i++) {

// Stuff here

}

In the future you may think to change the vector with a list, because the type of operations you have to do on it. Without typedef you have to change ALL occurrences of vector within your code. But if you write something like this:

将来你可能会想用一个列表来改变矢量,因为你要对它做的操作的类型。没有typedef,您必须更改代码中出现的所有向量。但是如果你这样写:

typedef vector<int> my_vect;

my_vect v;

...

for(my_vect::const_iterator i = v->begin(); i != v.end(); i++) {

// Stuff here

}

Now you just have to change one row of code (i.e from "typedef vector<int> my_vect" to "typedef list<int> my_vect") and everything works.

现在你只需要修改一行代码(i)。e从“typedef vector my_vect”到“typedef list my_vect”),一切正常。

typedef also saves you time when you have complex data structures which are very long to write (and difficult to read)

当您拥有复杂的数据结构时,typedef还可以节省您的时间,这些数据结构非常长(而且难于阅读)

#6


5  

One good reason to use typedef is if the type of something may change. For example, let's say that for now, 16-bit ints are fine for indexing some dataset because for the foreseeable future, you'll have less than 65535 items, and that space constraints are significant or you need good cache performance. However, on the off chance that you need to use your program on a dataset with more than 65535 items, you want to be able to easily switch to a wider integer. Use a typedef, and you only have to change this in one place.

使用typedef的一个很好的理由是如果某些东西的类型可能会改变。例如,假设目前16位的int对于某些数据集来说是可以的,因为在可预见的将来,您将拥有少于65535个项,并且空间约束非常重要,或者您需要良好的缓存性能。但是,如果您需要在包含超过65535项的数据集中使用程序,那么您希望能够轻松地切换到更大的整数。使用类型定义,您只需在一个地方更改它。

#7


4  

typedef allows to not only have an alias for complex types, but gives you an natural place to document a type. I sometimes use it for documentational purposes.

typedef不仅可以为复杂类型提供别名,还可以为您提供一个记录类型的自然位置。我有时用它来做记录。

There are also times when I use an array of bytes. Now, an array of bytes could mean a lot of things. typedef makes it handy to define my byte array as "hash32", or "fileContent" to make my code more readable.

有时我使用字节数组。现在,一个字节数组意味着很多事情。typedef可以方便地将字节数组定义为“hash32”或“fileContent”,以便使代码更具可读性。

#8


2  

Real-world uses of typedef:

实际使用的类型:

  • providing friendly aliases for long-winded templated types
  • 为冗长的模板类型提供友好的别名
  • providing friendly aliases for function pointer types
  • 为函数指针类型提供友好的别名
  • providing local labels for types, e.g.:

    为类型提供本地标签,例如:

    template<class _T> class A
    {
        typedef _T T;
    };
    
    template<class _T> class B
    {
        void doStuff( _T::T _value );
    };
    

#9


2  

There is one another use case to use typedef is when we want to enable a kind of Container Independent code (but not exactly!)

使用typedef还有另外一个用例,当我们想要启用某种容器独立的代码时(但不是完全如此!)

Let us say you have class:

假设你有课:

Class CustomerList{

public:
    //some function
private:
    typedef list<Customer> CustomerContainer;
    typedef CustomerContainer::iterator Cciterator;
};

The above code encapsulates the internal container implementation using typedef and even if in future the list container needs to changed to vector or deque still the user of the CustomerList class doesn't need to worry about exact container implementation.

上面的代码使用typedef封装内部容器实现,即使将来列表容器需要更改为vector或deque, CustomerList类的用户也不需要担心确切的容器实现。

Hence, the typedef encapsulates and somewhat help us to write Container Independent code

因此,typedef封装并在一定程度上帮助我们编写容器独立的代码

#10


0  

Whenever it makes the source clearer or better to read.

无论何时它使源文件更清晰或更好阅读。

I use kind of typedef in C# for generics/templates. A "NodeMapping" is just better to read/use and understand then a lot of "Dictionary<string, XmlNode>". IMHO. So I'd recommend it for templates.

我在c#中对泛型/模板使用某种类型定义。“NodeMapping”最好是读/使用,然后理解很多“字典 ”。恕我直言。所以我推荐它作为模板。 ,>

#11


0  

Typedef allows flexibility in your class. When you want to change the data type in the program, you do not need to change multiple locations but just need to change one occurrence.

Typedef允许您的类具有灵活性。当您想要更改程序中的数据类型时,您不需要更改多个位置,而只需更改一个事件。

typedef <datatype example  int or double> value_type

you can give nay name instead of value_type, but value_type is normally the standard name.

可以用nay型代替value_type,但value_type通常是标准名。

So u can use typedef like

所以你可以用类型定义

value_type i=0;     //same as a int or double i=0; 

#12


-1  

... and you Don't Need a Typedef for an enum or a struct.

…您不需要为enum或struct使用类型定义。

Or do you?

还是你?

typedef enum { c1, c2 } tMyEnum;
typedef struct { int i; double d; } tMyStruct;

can be better written as

可以写成更好的形式吗

enum tMyEnum { c1, c2 }
struct  tMyStruct { int i; double d; };

Is that correct? What about C?

那是正确的吗?C呢?