func createFinalStrings() -> [String] {
let substrings = createSubstrings()
var finalStrings = [String]()
let lastChars = substrings.flatMap { $0.characters.last }
for _ in 0...5 {
var string = ""
while string.characters.count < 3 {
let index = Int(arc4random_uniform(5))
let lastChar = lastChars[index]
if string.rangeOfString(String(lastChar)) == nil{
string = string + String(lastChar)
}
}
finalStrings.append(string)
}
return finalStrings
}
我用VC ++ 14.2和GCC 5.4.0测试了代码,两者都输出:
#include<iostream>
using namespace std;
struct B{};
struct A
{
A(const B &)
{
cout<<"A(const B &)"<<endl;
}
A(B &&)
{
cout<<"A(B &&)"<<endl;
}
};
A get()
{
B b;
return b;
}
int main()
{
get();
}
为什么输出不是
A(B &&)
此代码与A(const B &)
有任何关系吗? (但A和B是不同的类型,因此copy elision
不应该在这里工作)
答案 0 :(得分:29)
为了响应C ++ 14发布之前的评论,rvalue返回规则发生了变化。这个变化是在过程的后期添加的,并由CWG Issue 1579捕获,修改了12.8 / 32的措辞:
或
return
语句中的表达式是(可能带括号的) id-expression ,用于命名具有在正文中声明的自动存储持续时间的对象
这意味着返回任何局部变量现在将该变量指定的对象视为首先是rvalue(如果重载决策失败则再次尝试)。
由于CWG问题被接受为语言中的缺陷,编译器甚至可以在“C ++ 11模式”中实现这一新规则。缺陷的一点是“它始终意味着以这种方式工作”,所以这并不是严格意义上说C ++ 11和C ++ 14之间的变化,而是修改了C ++ 11的含义在2014年。
答案 1 :(得分:5)
复制elision与A相关,而不是在get()堆栈框架中构造。
会发生什么事情是返回的b
(因为&#34;因为返回&#34而临时死亡;这是因为C ++ 14),用于构建复制删除主堆栈框架中的A
。
因为临时对象绑定了你观察到的r值引用。