5

例如,我有一些类DataPacket。有什么区别:

auto packet = DataPacket(); 

DataPacket packet;

?

4

5 回答 5

14

首先回答这个问题auto,生成的代码之间没有区别:

auto packet = DataPacket(); 

DataPacket packet = DataPacket();

但这不是你写的。

在最初的问题中,第一个创建了一个值初始化的临时值,然后packet从中复制初始化。这需要一个可访问的非显式复制或移动构造函数,要求类型可以是默认构造的,并确保packet已初始化(假设复制/移动构造函数没有错误。)第二个默认初始化packet只需要type 可以是默认构造的,但如果它有一个普通的默认构造函数,则使对象未初始化,例如:

struct DataPacket { int i; };
{
  DataPacket packet = DataPacket();
  ++packet.i;  // OK
}
{
  DataPacket packet;
  ++packet.i;  // undefined behaviour
}

正如 Xeo 在下面的评论中指出的那样,这些之间的区别较小:

auto packet = DataPacket();

DataPacket packet{};

因为其中的第二个也确保了值初始化,所以在这种情况下,区别在于前者需要一个可访问的、非显式的复制或移动构造函数。

在所有需要可访问的复制/移动构造函数的情况下,如果没有省略复制(或移动),则生成的代码将因复制/移动而有所不同。但在实践中,所有现代编译器都会忽略它,因此生成的代码将是相同的。

于 2012-07-30T21:30:12.990 回答
10

第一个是复制初始化,如果没有复制或移动构造函数可访问,则会失败。

于 2012-07-30T20:55:01.743 回答
4

从编译器的角度来看,除了显式声明变量可以为变量指定父类型之外,没有区别。从风格上讲,它会影响可读性(尽管它是积极的还是消极的影响取决于人)。

编辑:正如所指出的,第一个执行复制构造,而第二个使用默认构造函数。在这里发现的差异的迂腐解释。

于 2012-07-30T20:52:09.743 回答
1

当您不知道某些表达式的类型时,auto 关键字会很有用。您实际上是在要求编译器在编译时确定变量的类型。就编译器而言,使用 auto 关键字和显式使用类型之间绝对没有区别。

您还可以使用 auto 关键字来确定函数的返回类型,该函数的返回类型在编译时才知道(某些模板函数会发生这种情况)。请参阅此 Wikipedia 文章:替代函数语法

请注意,auto 关键字不会为您提供 RTTI。自动类型在编译时静态确定。

回到旧的 C 时代,auto 关键字声明变量将“自动”存储在堆栈上,而不是存储在静态数据区域中。

于 2012-07-30T21:07:51.040 回答
0

在这种情况下,我建议使用第二种语法(不带“auto”关键字),因为它不那么冗长。

这是 auto 有意义的一个示例:

map<int, pair<string, double>> M;
.... // Fill up M
// Without "auto":
map<int, pair<string, double> >::iterator it = M.find(5);
// With "auto":
auto autoit = M.find(5);
// Yet another example:
// Without auto:
for (pair<const int, pair<string, double>>& x: M) {
   // Do stuff
}
// With auto:
for (auto& x : M) {
   // Do stuff
}
于 2012-07-30T21:05:18.250 回答