在VS2013更新5中,我有这个:
class Lock { public: Lock(CriticalSection& cs) : cs_(cs) {} Lock(const Lock&) = delete; Lock(Lock&&) = delete; Lock& operator=(const Lock&) = delete; Lock& operator=(Lock&&) = delete; ~Lock() { LeaveCriticalSection(&(cs_.cs_)); } private: CriticalSection& cs_; }; class CriticalSection { CRITICAL_SECTION cs_; public: CriticalSection(const CriticalSection&) = delete; CriticalSection& operator=(const CriticalSection&) = delete; CriticalSection(CriticalSection&&) = delete; CriticalSection& operator=(CriticalSection&&) = delete; CriticalSection() { InitializeCriticalSection(&cs_); } ~CriticalSection() { DeleteCriticalSection(&cs_); } // Usage: auto lock = criticalSection.MakeLock(); Lock MakeLock() { EnterCriticalSection(&cs_); return Lock(*this); } }
MakeLock
返回不可移动,不可复制类型的实例.这似乎工作正常.但是,Visual Studio intellisense确实强调了红色的返回,并警告说Lock的移动构造函数不能被引用,因为它是一个已删除的函数.
我试图理解为什么这有效,如果它是标准符合C++或只是MSVC特有的东西.我猜回归是有效的,因为构建返回值的需要可以被优化掉,所以intellisense警告会警告某些事情 - 实际上 - 实际上不会发生.
我想我在某处读到C++会标准化以确保返回值优化总是会发生.
那么,这个符合C++的代码是否会继续在未来的编译器中运行?
PS我意识到std::mutex
并std::lock_guard
可能取代它.
如果编译,则编译器中存在错误.VC2015无法正确编译它.
class Foo { public: Foo() {} Foo(const Foo&) = delete; Foo(Foo&&) = delete; }; Foo Bar() { return Foo(); }
给我:
xxx.cpp(327): error C2280: 'Foo::Foo(Foo &&)': attempting to reference a deleted function
和g ++ 4.9说:
error : use of deleted function 'Foo::Foo(Foo&&)'
标准非常清楚,复制构造函数或移动构造函数必须存在且可访问,即使RVO意味着它未被调用.
在C++ 17中,Martin Bonner的答案中的代码是合法的.
编译器不仅被允许,而且还有义务忽略该副本.Clang和GCC的实例.C++ 17 6.3.2/2(强调我的):
[...] [注意:如果操作数不是prvalue或者其类型与函数的返回类型不同,则返回语句可能涉及调用构造函数以执行操作数的复制或移动.如果返回自动存储持续时间变量(10.9.5),则可以省略与返回语句相关联的复制操作或将其转换为移动操作. - 结束说明]
这里的prvalue意味着一个临时的.有关确切的定义和大量示例,请参见此处.
在C++ 11中,这确实是非法的.但它很容易解决,通过在return语句中使用大括号初始化,您可以在调用站点位置构造返回值,完美地绕过了经常被省略的复制构造函数的要求.C++ 11 6.6.3/2:
[...]带有braced-init-list的return语句通过copy-list-initialization(8.5.4)从指定的初始化列表初始化要从函数返回的对象或引用.[...]
复制列表初始化意味着只调用构造函数.不涉及复制/移动构造函数.
Clang和GCC的实例.
不幸的是,它既不适用于Visual Studio编译器的任何最新版本,也很难受,并且保持其糟糕的C++一致性声誉.返回像这样的非可复制对象是一个非常强大的构造,用于std::lock_guard
从函数返回例如s(允许您轻松地保持std::mutex
成员私有)等.