C ++ 11 中的 'typedef' 和 'using' 有什么区别?

typedef int MyInt;
using MyInt = int;
template< class T > using MyType = AnotherType< T, MyAllocatorType >;

答案

它们等效于标准(重点是我的)(7.1.3.2):

typedef 名称也可以通过别名声明来引入。 using 关键字后面的标识符变为 typedef 名称,而标识符后面的可选 attribute-specifier-seq 属于该 typedef 名称。 它具有与 typedef 说明符引入的语义相同的语义。特别是,它没有定义新的类型,也不应出现在 type-id 中。

它们基本相同,除了:

别名声明与模板兼容,而 C 风格的 typedef 不兼容。

在模板中使用时, using语法具有优势。如果需要类型抽象,还需要保留模板参数,以便将来可以指定。你应该这样写。

template <typename T> struct whatever {};

template <typename T> struct rebind
{
  typedef whatever<T> type; // to make it possible to substitue the whatever in future.
};

rebind<int>::type variable;

template <typename U> struct bar { typename rebind<U>::type _var_member; }

但是使用语法可以简化此用例。

template <typename T> using my_type = whatever<T>;

my_type<int> variable;
template <typename U> struct baz { my_type<U> _var_member; }

它们本质上是相同的,但是using提供了非常有用的alias templates 。我可以找到一个很好的例子,如下所示:

namespace std {
 template<typename T> using add_const_t = typename add_const<T>::type;
}

因此,我们可以使用std::add_const_t<T>代替typename std::add_const<T>::type

我知道原始发帖人的回答很好,但是对于像我这样绊脚石的任何人,提案中都有一条重要说明,我认为这对此处的讨论特别是对typedef关键字是否在注释中的关注增加了一些价值。将来将被标记为已弃用,或由于冗余 / 旧而被删除:

已建议(重新)使用关键字 typedef ... 引入模板别名:

template<class T>
  typedef std::vector<T, MyAllocator<T> > Vec;

该符号的优点是使用已知的关键字来引入类型别名。但是,它也显示了一些不足之处,其中,在别名不是指定类型而是模板的情况下,使用已知为类型名称引入别名的关键字会造成混淆。 Vec 不是类型的别名,并且不应将其用作 typedef 名称。 Vec名称是std::vector<•, MyAllocator<•> >家族的名称–其中项目符号是类型名称的占位符。因此,我们不建议使用 “typedef” 语法。句子

template<class T>
  using Vec = std::vector<T, MyAllocator<T> >;

可以理解为: 从现在开始,我将使用Vec<T>作为std::vector<T, MyAllocator<T> >的同义词 。通过阅读,别名的新语法似乎是合理的。

对我而言,这意味着将继续支持 C ++ 中的typedef关键字,因为它仍然可以使代码更具可读性和可理解性

更新using关键字是专门为模板,并(在接受的答案指出)当你与非模板工作usingtypedef是机械上相同的,所以在选择完全取决于可读性的理由,程序员和目的沟通。

这两个关键字是等效的,但有一些警告。一种是using T = int (*)(int, int);声明函数指针using T = int (*)(int, int);比使用typedef int (*T)(int, int);更清晰typedef int (*T)(int, int); 。其次是typedef无法使用模板别名形式。第三是公开 C API 需要在公共头文件中使用typedef