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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/516237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:45:26  来源:igfitidea点击:

When should I use typedef in C++?

c++typedef

提问by djeidot

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 typedefis preferred? Or is this really more a C-specific keyword?

在我多年的 C++ (MFC) 编程中,我从未觉得需要使用typedef,所以我真的不知道它是用来做什么的。我应该在哪里使用它?是否有任何实际情况typedef优先使用?或者这真的更像是一个特定于 C 的关键字?

回答by j_random_hacker

Template Metaprogramming

模板元编程

typedefis necessaryfor many template metaprogrammingtasks -- whenever a class is treated as a "compile-time type function", a typedefis 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:

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

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*>::typeevaluates to double. Note that template metaprogramming is not commonly used outside of library development.

示例:类型表达式的strip_pointer_from<double*>::type计算结果为double。请注意,模板元编程在库开发之外并不常用。

Simplifying Function Pointer Types

简化函数指针类型

typedefis helpfulfor 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) {
    ...
}

回答by Jason Punyon

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 int32everywhere 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,那么您只需更改typdef

typedef long int32;

and your program will still work on the new implementation.

并且您的程序仍将适用于新的实现。

回答by yesraaj

use with function pointer

与函数指针一起使用

Hide Function Pointer Declarations With a typedef

使用 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 且不带参数的函数的指针”声明一个 typedef,如下所示:

  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 并采用 pfv 的函数的指针”声明另一个 typedef:

 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 typedef 作为笨拙的“指向返回 void 并采用 pfv 的函数的指针”的同义词,声明一个包含 10 个这样的指针的数组是轻而易举的:

  pf_taking_pfv p[10];

from

回答by peterchen

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

甚至使用像这样的 typedef 也很常见

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 的前向声明,其声明的优点之一是与前向声明一起使用是安全的。

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.

容器 typedefs 我通常在容器变量被声明的地方使用——例如,当实际容器实例是类成员时,本地变量作为类成员。如果实际的容器类型是一个实现细节,这很有效 - 不会导致额外的依赖。

If they become part of a particularinterface, 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).

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

回答by Emiliano

typedef is useful in a lot of situations.

typedef 在很多情况下都很有用。

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++ 向量上进行迭代

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,您必须更改代码中所有出现的 vector。但是如果你写这样的东西:

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.

现在您只需更改一行代码(即从“ typedef vector<int> my_vect” 到“ typedef list<int> my_vect”),一切正常。

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

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

回答by dsimcha

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 位整数适合索引某些数据集,因为在可预见的未来,您将拥有少于 65535 个项目,并且空间限制很大或者您需要良好的缓存性能。但是,如果您需要在包含超过 65535 个项目的数据集上使用您的程序,您希望能够轻松切换到更宽的整数。使用 typedef,您只需在一个地方更改它。

回答by Ztyx

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

typedef不仅允许为复杂类型使用别名,而且还为您提供一个自然的位置来记录类型。我有时将它用于文档目的。

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

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

回答by Imran Al Noor

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 封装并在一定程度上帮助我们编写容器独立代码

回答by moonshadow

Real-world uses of typedef:

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 );
    };
    
  • 为冗长的模板类型提供友好的别名
  • 为函数指针类型提供友好的别名
  • 为类型提供本地标签,例如:

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

回答by Leonidas

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# 中使用 typedef 来表示泛型/模板。“NodeMapping”比很多“Dictionary<string, XmlNode>”更易于阅读/使用和理解。恕我直言。所以我推荐它用于模板。