我想知道是否可以在snprintf
中使用ostream
格式,以便我可以在流表达式中嵌入对snprintf
的调用。这在GCC 4.9中编译,但是可以吗?
cout << [](char (&&buf) [12], int d) { snprintf(buf, 12, "%d", d); return buf; } ({ }, 15) << endl;
答案 0 :(得分:7)
这是良好的形式和明确的定义。 {}
用于将rvalue引用的copy-list-initialize初始化为char [12]
,这将创建一个绑定引用的临时char [12]
数组。这个临时值一直持续到完整表达式结束 - 在这种情况下,直到分号,因此可以安全地返回指向数组中元素的指针并用于在该表达式中打印。 (lambda返回指向此数组的第一个元素的char *
。)
Standardese:
§8.5[dcl.init] / p17:
初始化器的语义如下。 [...]
- 如果初始化程序是(非括号内的) braced-init-list ,则对象或引用是列表初始化的(8.5.4)。
§8.5.4[dcl.init.list] / p3:
定义了
T
类型的对象或引用的列表初始化 如下:
- [...]
- 否则,如果
T
是引用类型,则T
引用的类型的prvalue临时值是copy-list-initialized或 direct-list-initialized,取决于初始化的类型 引用,引用绑定到临时。 [注意: 像往常一样,绑定将失败,程序是不正确的,如果 reference类型是对非const类型的左值引用。 - 结束记录 ]
§12.2[class.temporary] / p5:
临时绑定到函数调用中的引用参数(5.2.2) 一直持续到包含完整表达式的完整表达式 调用
答案 1 :(得分:3)
我很确定这没关系。如果我理解正确,lambda将返回类型为char[12]
的对象作为临时对象(来自自动返回类型推导)。然后可以将该临时文件传递给另一个函数,在本例中为operator<<()
。
它可能意味着复制,但RVO可能会照顾它。
更新
正如评论和T.C.提供的更好的答案所述,这个lambda推导出的返回类型实际上是char *而不是char [12]。我已经通过GCC中的代码确认了这一点。