2016-09-14 60 views
95

这句话是什么在C++ 11中,“return {}”语句的含义是什么?

return {}; 

在C++ 11指示,以及何时使用它,而不是(说)

return NULL; 

return nullptr; 
+54

它返回函数返回类型的默认构造实例。 –

+0

或者简单的'return;'没有价值? – i486

+0

不,正如讨论所揭示的那样,如果你的函数应该返回一些东西(即不是void返回类型)并且你只写了'return;'另一方面'return {};'是有效的你有一个返回类型。 – Pedia

回答

93

return {};表示“返回一个空list-initializer初始化函数的返回类型的对象”。确切的行为取决于返回的对象的类型。

cppreference.com(因为OP被标记C++ 11,I排除C++ 14和C++ 17的规则是指该链接的其他细节):

  • 如果braced-init-list是空的,而T是具有默认构造函数的类类型,则执行值初始化。
  • 否则,如果T是聚合类型,则执行聚合初始化。
  • 否则,如果T是std :: initializer_list的特化,则T对象将根据上下文从braced-init-list直接初始化或复制初始化。
  • 否则,T的构造都认为,在两个阶段:

    • 所有构造函数采取的std :: initializer_list作为唯一的参数,或者作为第一个参数,如果其余的参数有默认值,是通过重载决议匹配std :: initializer_list
    • 如果前一阶段没有产生匹配,T的所有构造函数都会参与重载解析,这是针对由braced-init-list,限制只允许非缩小转换。如果这个阶段产生一个显式构造函数作为复制列表初始化的最佳匹配,编译失败(注意,在简单的复制初始化中,根本不考虑显式构造函数)。
  • 否则(如果T是不是类型)中,如果支撑-INIT列表仅具有一个元素,或者T是不是引用类型或引用类型是与类型兼容元素T直接初始化(在直接列表初始化中)或复制初始化(在复制列表初始化中),除了不允许缩小转换之外。

  • 否则,如果T是与元素的类型不兼容的引用类型。 (如果引用是非const左值引用,则失败)
  • 否则,如果braced-init-list没有元素,则T进行了值初始化。

之前C++ 11,返回一个std::string的功能,你会写:

std::string get_string() { 
    return std::string(); 
} 

使用C++ 11的支柱语法,你不需要重复类型:

std::string get_string() { 
    return {}; // an empty string is returned 
} 

return NULLreturn nullptr时,应使用该函数返回一个指针类型:

any_type* get_pointer() { 
    return nullptr; 
} 

然而,NULL是因为C++ 11推荐使用,因为它只是一个别名为整数值(0),而nullptr是一个真正的指针类型:

int get_int() { 
    return NULL; // will compile, NULL is an integer 
} 

int get_int() { 
    return nullptr; // error: nullptr is not an integer 
} 
87

这可能是令人困惑:

int foo() 
{ 
    return {}; // honestly, just return 0 - it's clearer 
} 

这可能不是:

SomeObjectWithADefaultConstructor foo() 
{ 
    return {}; 
    // equivalent to return SomeObjectWithADefaultConstructor {}; 
} 
+9

因此,如果返回类型没有默认构造函数,那么这是一个编译时错误,是否正确? – Pedia

+1

@KarimPedia它当然应该是。 –

+9

如果返回类型是一个没有_non-explicit_默认构造函数且不是聚合的类,那么这是一个编译错误。 – Oktalist

24

return {};意味着{}是初始值设定为返回值。返回值是用空列表进行列表初始化的。


这里是关于返回值一些背景下,根据[stmt.return]在C++标准:

对于由值返回一个函数(即,返回类型不是一个参考而不是void),有一个临时对象称为返回值。此对象由return语句创建,其初始化程序取决于返回语句中的内容。

返回值一直存在,直到调用该函数的代码中的全表达式结束;如果它具有类类型,那么它的析构函数将运行,除非它的生命周期由调用者直接绑定一个引用来扩展。

返回值可以通过两种不同的方式进行初始化:


假设T是函数的返回类型,然后记下return T{};return {}不同:前者,临时T{}被创建,然后返回值是复制初始化从临时。

如果T没有可访问的复制/移动构造函数,这将无法编译,但return {};将成功,即使这些构造函数不存在。因此,return T{};可能会显示副本构造函数等的副作用,尽管这是一个复制elision上下文,因此它可能不会。


这里的列表初始化采用简短的回顾一下C++ 14(N4140 [dcl.init.list]/3),其中,所述初始化是一个空列表:

  • 如果T是一个聚合,然后每个成员从它的括号或等号初始化程序初始化,如果它有一个,否则就像{}(所以递归地应用这些步骤)。
  • 如果T是一个具有用户提供的默认构造函数的类类型,则调用该构造函数。
  • 如果T是一个具有隐式定义或缺省构造函数的类类型,则该对象为zero-initialized,然后调用默认构造函数。
  • 如果Tstd::initializer_list,则返回值是一个空的此类列表。
  • 否则(即T是非类类型 - 返回类型不能是数组),返回值是零初始化的。
+0

Aggregate init首先出现,它用'{}'递归地初始化每个成员,这可能是也可能不是value-init。 –

+0

@ T.C。对,我去了cppreference,但忽略了一个“直到C++ 14” –

3

对于方法返回类型的新实例来说,这是一种简短的手段。

相关问题