“ return {}”语句在 C + + 11中是什么意思?

这个声明

return {};

在 C + + 11中表示,以及什么时候用它来代替(比如)

return NULL;

或者

return nullptr;
37036 次浏览

这可能令人困惑:

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

这可能不是:

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

return {};表示“返回用空 列表初始化程序初始化的函数返回类型的对象”。确切的行为取决于返回对象的类型。

Cppreference.com开始(因为 OP 被标记为 C + + 11,我排除了 C + + 14和 C + + 17中的规则; 请参考链接了解更多细节) :

  • 如果大括号 init-list 为空,而 t 是带有缺省构造函数的类类型,则执行值初始化。
  • Otherwise, if T is an aggregate type, aggregate initialization is performed.
  • 否则,如果 T 是 std: : initializer _ list 的专门化,则 T 对象将从支撑的 init-list 中直接初始化或复制初始化(取决于上下文)。
  • Otherwise, the constructors of T are considered, in two phases:

    • 检查所有将 std: : initializer _ list 作为唯一参数的构造函数,或者如果其余参数具有默认值,则将其作为第一个参数的构造函数,并通过重载解析对单个类型为 std: : initializer _ list 的参数进行匹配
    • If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all).
  • 否则(如果 T 不是类类型) ,如果大括号初始化列表只有一个元素,并且 T 不是引用类型或者是与元素类型兼容的引用类型,则 T 是直接初始化(在直接列表初始化中)或复制初始化(在拷贝列表初始化中) ,除非不允许进行收缩转换。

  • 否则,如果 T 是与元素类型不兼容的引用类型。(如果引用是非常量左值引用,则此操作失败)
  • 否则,如果大括号 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只是整数值(0)的别名,因此 C + + 11不推荐使用 NULL,而 nullptr是真正的指针类型:

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


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

return {};意味着 {}return value的初始化器。返回值用一个空列表初始化。


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

对于通过值返回的函数(即返回类型不是引用,也不是 void) ,有一个称为 返回值的临时对象。此对象由 return语句创建,其初始化器取决于 return 语句中的内容。

返回值存活到调用函数的代码中的完整表达式结束为止; 如果它具有类类型,那么它的析构函数将运行,除非它的生存期被调用者直接绑定到它的引用所延长。

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


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

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


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

  • 如果 T是一个聚合,那么每个成员都从它的 大括号或等于初始值设定项初始化(如果它有的话) ,否则就像通过 {}一样(因此递归地应用这些步骤)。
  • If T is a class type with a user-provided default constructor, that constructor is called.
  • If T is a class type with an implicitly-defined, or = defaulted default constructor, the object is zero-initialized and then the default constructor is called.
  • 如果 Tstd::initializer_list,则返回值为空的此类列表。
  • 否则(例如,T是非类类型——返回类型不能是数组) ,返回值是零初始化的。

它是方法返回类型的新实例的一种简写。