Den*_*ose 10 c++ rvalue-reference c++11
第一:在哪里std::move
和std::forward
界定?我知道他们做了什么,但我找不到任何标准标题包含它们的证据.在gcc44中,有时std::move
可用,有时则不可用,因此明确的include指令会很有用.
在实现移动语义时,源可能处于未定义状态.该状态是否必须是对象的有效状态?显然,您需要能够调用对象的析构函数,并能够通过类暴露的任何方式为其分配.但其他操作是否有效?我想我要问的是,如果你的班级保证某些不变量,当用户说他们不再关心它们时你是否应该努力强制执行这些不变量?
下一篇:当你不关心移动语义时,是否有任何限制会导致非const引用在处理函数参数时优于rvalue引用? void function(T&);
在void function(T&&);
从呼叫者的角度来看,能够传递功能的临时值是偶尔有用,所以它好像应该授予该选项时,它是可行的,这样做的.并且rvalue引用本身就是lvalues,因此你不能无意中调用move-constructor而不是copy-constructor,或类似的东西.我没有看到一个缺点,但我确信有一个.
这让我想到了最后一个问题.您仍然无法将临时对象绑定到非const引用.但是您可以将它们绑定到非const右值引用.然后,您可以将该引用作为另一个函数中的非const引用传递.
void function1(int& r) { r++; }
void function2(int&& r) { function1(r); }
int main() {
function1(5); //bad
function2(5); //good
}
Run Code Online (Sandbox Code Playgroud)
除了它没有做任何事情之外,该代码有什么问题吗?我的直觉当然不是,因为改变右值参考是他们存在的一个重点.如果传递的值是合法的const,编译器将捕获它并对你大喊大叫.但从各方面来看,这是一个机制的一个周期,可能是因为某种原因而存在,所以我只是想确认我没有做任何愚蠢的事情.
Joh*_*itb 10
第一:std :: move和std :: forward定义在哪里?
请参见20.3
实用程序组件<utility>
.
在实现移动语义时,源可能处于未定义状态.该状态是否必须是对象的有效状态?
显然,该物体仍应是可破坏的.但除此之外,我认为仍然可以分配是一个好主意.标准说对于满足"MoveConstructible"和"MoveAssignable"的对象:
[注意:rv仍然是一个有效的对象.其状态未指明. - 结束说明]
我认为,这意味着该对象仍然可以参与任何不表示任何先决条件的操作.这包括CopyConstructible,CopyAssignable,Destructible等.请注意,从核心语言的角度来看,这对于您自己的对象不需要任何内容.只有在您触摸表明这些要求的标准库组件时才会发生这些要求.
下一篇:当你不关心移动语义时,是否有任何限制会导致非const引用在处理函数参数时优于rvalue引用?
遗憾的是,这关键取决于参数是否在函数模板中并使用模板参数:
void f(int const&); // takes all lvalues and const rvalues
void f(int&&); // can only accept nonconst rvalues
Run Code Online (Sandbox Code Playgroud)
但是对于功能模板
template<typename T> void f(T const&);
template<typename T> void f(T&&);
Run Code Online (Sandbox Code Playgroud)
你不能这么说,因为在用左值调用之后,第二个模板将具有作为合成声明的参数的U&
nonconst lvalues 的类型(并且是更好的匹配),以及U const&
const lvalues(并且是不明确的).据我所知,没有部分排序规则来消除第二种歧义的歧义.但是,这已经知道了.
--
编辑 --
尽管有这个问题报告,但我认为这两个模板并不含糊.部分排序会使第一个模板更加专业化,因为在删除了引用修饰符之后const
,我们会发现两个类型都是相同的,然后注意第一个模板对const的引用.标准说(14.9.2.4
)
如果对于给定类型,推导在两个方向上都成功(即,在上面的转换之后类型是相同的)并且如果参数模板中的类型比参数模板中的类型更具cv-quali ed(如如上所述)该类型被认为比另一类更专业.
如果对于每种类型被认为是给定的模板至少对所有类型都是专用的,并且对于某些类型更专用,而另一个模板对于任何类型都不是更专用的,或者至少不是对任何类型的专用,那么给定的模板比其他模板更专业.
这使得T const&
模板成为部分排序的胜利者(GCC确实是正确的选择它).
--
编辑结束 --
这让我想到了最后一个问题.您仍然无法将临时对象绑定到非const引用.但是您可以将它们绑定到非const右值引用.
这篇文章很好地解释了这一点.第二次调用function2
仅使用非对齐rvalues.程序的其余部分将不会注意到它们是否被修改,因为它们之后将无法再访问这些rvalues!并且5
您传递的不是类类型,因此创建隐藏的临时值,然后传递给int&&
右值引用.代码调用function2
将无法在此处访问该隐藏对象,因此它不会发现任何更改.
不同的情况是,如果你这样做:
SomeComplexObject o;
function2(move(o));
Run Code Online (Sandbox Code Playgroud)
您已明确请求o
移动,因此将根据其移动规范进行修改.但是,移动是一种逻辑上不可修改的操作(参见文章).这意味着您是否应该从调用代码中观察到是否移动:
SomeComplexObject o;
moveit(o); // #1
o = foo;
Run Code Online (Sandbox Code Playgroud)
如果删除移动的行,行为仍将是相同的,因为它仍然被覆盖.然而,这意味着使用其o
之后的值的代码被移除是不好的,因为它打破moveit
了调用代码之间的隐式契约.因此,标准没有规定从容器移动的具体值.
归档时间: |
|
查看次数: |
1582 次 |
最近记录: |