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

时间:2016-09-14 09:33:42

标签: c++ c++11 return return-value list-initialization

声明是什么

return {};
C ++ 11中的

表示,何时使用它代替(比如说)

return NULL;

return nullptr;

4 个答案:

答案 0 :(得分:100)

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

cppreference.com开始(因为OP标记为C ++ 11,我排除了C ++ 14和C ++ 17中的规则;请参阅该链接以获取更多详细信息):

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

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

  •   
  • 否则,如果T是与元素类型不兼容的引用类型。 (如果引用是非常量左值引用,则会失败)
  •   
  • 否则,如果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;
}

但是,{C} 11之后不推荐使用NULL,因为它只是整数值(0)的别名,而nullptr是真正的指针类型:

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

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

答案 1 :(得分:89)

这可能令人困惑:

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

这可能不是:

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

答案 2 :(得分:26)

return {};表示{}返回值的初始值设定项。返回值使用空列表进行列表初始化。

以下是返回值的背景知识,基于C ++标准中的[stmt.return]:

对于按值返回的函数(即返回类型不是引用而不是void),有一个名为返回值的临时对象。此对象由return语句创建,其初始值设定项取决于return语句中的内容。

返回值一直存在,直到调用该函数的代码中的full-expression结束;如果它有类类型,那么它的析构函数将会运行,除非调用者将引用直接绑定到它上,它将延长生命周期。

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

假设T是函数的返回类型,请注意return T{};return {}不同:在前者中,创建了临时T{},然后< em>返回值是从该临时值复制初始化的。

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

以下是C ++ 14(N4140 [dcl.init.list] / 3)中 list-initialization 的简要回顾,其中初始化器是一个空列表:

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

答案 3 :(得分:3)

对于方法返回类型的新实例,这是一种简写。