vsc*_*ech 15 const return rvalue-reference move-semantics c++11
struct STest : public boost::noncopyable {
STest(STest && test) : m_n( std::move(test.m_n) ) {}
explicit STest(int n) : m_n(n) {}
int m_n;
};
STest FuncUsingConst(int n) {
STest const a(n);
return a;
}
STest FuncWithoutConst(int n) {
STest a(n);
return a;
}
void Caller() {
// 1. compiles just fine and uses move ctor
STest s1( FuncWithoutConst(17) );
// 2. does not compile (cannot use move ctor, tries to use copy ctor)
STest s2( FuncUsingConst(17) );
}
Run Code Online (Sandbox Code Playgroud)
上面的例子说明了如何在C++ 11中,如在Microsoft Visual C++ 2012中实现的,函数的内部细节可以修改其返回类型.直到今天,我的理解是返回类型的声明是程序员需要知道的,以了解如何处理返回值,例如,当作为参数传递给后续函数调用时.不是这样.
我喜欢const
在适当的地方制作局部变量.它帮助我清理思路并清楚地构建算法.但要注意返回声明的变量const
!即使变量将不再被访问(return
毕竟执行了一个语句),即使声明的变量const
已经超出范围(参数表达式的评估已经完成),它也无法移动,因此被复制(如果无法复制则无法编译).
这个问题与另一个问题有关,Move语义和返回const值.不同之处在于,在后者中,声明函数返回一个const
值.在我的例子中,FuncUsingConst
声明返回一个volatile临时的.然而,函数体的实现细节会影响返回值的类型,并确定返回的值是否可以用作其他函数的参数.
这种行为是否符合标准?
这如何被视为有用?
额外的问题:编译器如何知道编译时的差异,因为调用和实现可能在不同的翻译单元中?
编辑:尝试重新解释这个问题.
如果函数的结果多于声明的返回类型,那怎么可能?如果函数声明不足以确定函数返回值的行为,它甚至看起来是否可以接受?对我来说,似乎是FUBAR的一个案例,我只是不确定是否应该责怪标准或微软的实施.
作为被调用函数的实现者,我不能指望所有调用者都知道,更不用说监视调用代码中的每一个小变化.另一方面,作为调用函数的实现者,我不能依赖被调用的函数来返回在函数实现的范围内恰好被声明为const的变量.
功能声明是合同.现在有什么价值?我们不是在讨论语义上等效的编译器优化,比如copy elision,这很好但不会改变代码的含义.是否调用copy ctor 确实改变了代码的含义(甚至可以将代码破坏到无法编译的程度,如上所示).要理解我在这里讨论的尴尬,请考虑上面的"红利问题".
And*_*owl 16
我喜欢在适当的地方创建局部变量const.它帮助我清理思路并清楚地构建算法.
这确实是一种很好的做法.const
尽可能使用.但是,在这里,您不能(如果您希望const
移动对象).
const
在函数内部声明一个对象的事实是,只要对象处于活动状态,就不会改变对象的状态 - 换句话说,在调用析构函数之前从未改变过.甚至在调用析构函数之前也没有.只要它还活着,const
物体的状态就不会改变.
但是,在这里,你可以某种程度上期望这个对象在它被淹没范围之前从右边移动,并且移动正在改变状态.您无法从const
对象移动- 即使您不再使用该对象也是如此.
但是,您可以做的是创建一个非const
对象,并仅通过const
绑定到该对象的引用在您的函数中访问它:
STest FuncUsingConst(int n) {
STest object_not_to_be_touched_if_not_through_reference(n);
STest const& a = object_not_to_be_touched_if_not_through_reference;
// Now work only with a
return object_not_to_be_touched_if_not_through_reference;
}
Run Code Online (Sandbox Code Playgroud)
通过一些规则,您可以轻松地强制执行函数创建后不应该修改该对象的语义 - 除了在返回时允许它从中移动.
更新:
正如balki在评论中所建议的那样,另一种可能性是将常量引用绑定到非const临时对象(其生命周期将根据§12.2/ 5延长),并const_cast
在返回时执行:
STest FuncUsingConst(int n) {
STest const& a = STest();
// Now work only with a
return const_cast<STest&&>(std::move(a));
}
Run Code Online (Sandbox Code Playgroud)
如果对象的复制/移动构造函数 [...] 被隐式使用 odr,并且特殊成员函数不可访问,则程序是格式错误的
-- n3485 C++ 标准草案 [class.copy]/30
我怀疑你的问题是 MSVC 2012,而不是 C++11。
这段代码,即使不调用它,也不是合法的 C++11:
struct STest {
STest(STest const&) = delete
STest(STest && test) : m_n( std::move(test.m_n) ) {}
explicit STest(int n) : m_n(n) {}
int m_n;
};
STest FuncUsingConst(int n) {
STest const a(n);
return a;
}
Run Code Online (Sandbox Code Playgroud)
因为没有合法的方法可以变成a
返回值。虽然可以省略返回值,但省略返回值并不能消除复制构造函数存在的要求。
如果 MSVC2012 允许FuncUsingConst
编译,则违反了 C++11 标准。
归档时间: |
|
查看次数: |
1020 次 |
最近记录: |