下面的snipplet是否正确用于取消定义所有其他方法和类的构造函数?
struct Picture {
// 'explicit': no accidental cast from string to Picture
explicit Picture(const string &filename) { /* load image from file */ }
// no accidental construction, i.e. temporaries and the like
Picture() = delete;
// no copy
Picture(const Picture&) = delete;
// no assign
Picture& operator=(const Picture&) = delete;
// no move
Picture(Picture&&) = delete;
// no move-assign
Picture& operator=(Picture&&) = delete; // return type correct?
};
Run Code Online (Sandbox Code Playgroud)
这会删除每个默认的编译器实现,只留下析构函数,对吧?没有它,我猜这个类(几乎)无法使用,但我也可以删除它,对吗?
Picture&move-assign 的返回类型operator=(Picture&&)是否正确?如果我Picture&&为回归类型写的,它会有所作为吗?
c++ operator-overloading rvalue-reference move-semantics c++11
我正在编写从其他库中包含很多功能和方法的库.为了避免复制返回值我正在这样应用std::forward:
template<class T>
T&& wrapper(T&& t) {
f(t); // t passed as lvalue
return std::forward<T>(t);
}
Run Code Online (Sandbox Code Playgroud)
f返回void并获取T&&(或超载值).包装器总是返回包装器的参数,返回值应该保留参数的值.我是不是真的需要使用std::forward的return?RVO会让它变得多余吗?它是参考(R或L)的事实是否是多余的?如果return不是最后一个函数语句(在some if中),是否需要它?
如果wrapper()应该返回void或者是有争议的T&&,因为调用者可以通过arg访问评估值(参考,R或L).但在我的情况下,我需要返回值,以便wrapper()可以在表达式中使用.
它可能与这个问题无关,但众所周知,函数f不会被窃取t,所以第一次使用std::forwardin f(std::forward<T>(t))是多余的,它被我删除了.
我写过小测试:https://gist.github.com/3910503
测试显示,返回未转发T- 确实在gcc48和clang32中创建了额外的副本与-O3(RVO没有启动).
此外,我无法从UB中获得不良行为:
auto&& tmp = wrapper(42);
Run Code Online (Sandbox Code Playgroud)
它没有证明任何原因,因为它是未定义的行为(如果它是UB).
外部资源(如std::vector<T>或std::string)的"值类型"问题是复制它们往往非常昂贵,并且副本是在各种上下文中隐式创建的,因此这往往是性能问题.C++ 0x对这个问题的回答是移动语义,它在概念上基于资源窃取的思想,并且由rvalue引用技术驱动.
D是否有类似于移动语义或右值引用的东西?
我想将一个rvalue传递std::bind给一个在C++ 0x中采用rvalue引用的函数.我无法弄清楚该怎么做.例如:
#include <utility>
#include <functional>
template<class Type>
void foo(Type &&value)
{
Type new_object = std::forward<Type>(value); // move-construct if possible
}
class Movable
{
public:
Movable(Movable &&) = default;
Movable &operator=(Movable &&) = default;
};
int main()
{
auto f = std::bind(foo<Movable>, Movable());
f(); // error, but want the same effect as foo(Movable())
}
Run Code Online (Sandbox Code Playgroud) 我想知道我的构造者最好的形式.以下是一些示例代码:
class Y { ... }
class X
{
public:
X(const Y& y) : m_y(y) {} // (a)
X(Y y) : m_y(y) {} // (b)
X(Y&& y) : m_y(std::forward<Y>(y)) {} // (c)
Y m_y;
}
Y f() { return ... }
int main()
{
Y y = f();
X x1(y); // (1)
X x2(f()); // (2)
}
Run Code Online (Sandbox Code Playgroud)
据我所知,这是编译器在每种情况下都能做到的最好的.
(1a)y被复制到x1.m_y(1份)
(1b)将y复制到X的构造函数的参数中,然后复制到x1.m_y(2个副本)
(1c)y移入x1.m_y(1移动)
(2a)将f()的结果复制到x2.m_y(1份)
(2b)将f()构造成构造函数的参数,然后复制到x2.m_y(1个副本)
(2c)在堆栈上创建f(),然后移入x2.m_y(1 move)
现在几个问题:
在这两个方面,传递const引用并不差,有时候比传递值更好.这似乎违背了"想要速度?通过价值"的讨论..对于C++(不是C++ 0x),我应该坚持使用const引用作为这些构造函数,还是应该通过值传递?对于C++ 0x,我应该通过rvalue引用传递值吗?
对于(2),如果临时直接构造成x.m_y,我更喜欢.我认为即使是rvalue版本也需要一个移动,除非对象分配动态内存,否则移动与复制一样多.有没有办法对此进行编码,以便允许编译器避免这些副本和移动?
我已经在我认为编译器可以做得最好的事情和我自己的问题中做了很多假设.如果不正确,请更正其中任何一项.
我一直在探索C++ 中Move Constructors的可能性,我想知道在下面的例子中有哪些方法可以利用这个功能.考虑以下代码:
template<unsigned int N>
class Foo {
public:
Foo() {
for (int i = 0; i < N; ++i) _nums[i] = 0;
}
Foo(const Foo<N>& other) {
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other) {
// ??? How can we take advantage of move constructors here?
}
// ... other methods and members
virtual ~Foo() { /* no action required */ }
private:
int _nums[N];
};
Foo<5> bar() …Run Code Online (Sandbox Code Playgroud) 你能否在某些情况下给我一个说明性的例子来证明以下陈述是有用和必要的?
AnyTypeMovable v;
AnyTypeMovable&& r = move(v);
Run Code Online (Sandbox Code Playgroud) 有时将复杂或长表达式分成多个步骤是明智的(例如,第二个版本不是更清楚,但它只是一个例子):
return object1(object2(object3(x)));
Run Code Online (Sandbox Code Playgroud)
可以写成:
object3 a(x);
object2 b(a);
object1 c(b);
return c;
Run Code Online (Sandbox Code Playgroud)
假设所有3个类都实现了以rvalue作为参数的构造函数,第一个版本可能更快,因为临时对象被传递并可以移动.我假设在第二个版本中,局部变量被认为是左值.但是如果以后没有使用变量,那么C++ 11编译器是否会优化代码,因此变量被认为是rvalues,两个版本的工作方式完全相同?我最感兴趣的是Visual Studio 2013的C++编译器,但我也很高兴知道GCC编译器在这个问题上的行为.
谢谢,米哈尔
如果我有一个带有n个参数的构造函数,那么任何参数都可以是rvalue和lvalue.是否可以通过为rvalues移动语义来支持这一点,而无需为每个可能的rvalue/lvalue组合编写2 ^ n个构造函数?
最常见的用法std::forward是,完美地转发转发(通用)引用,例如
template<typename T>
void f(T&& param)
{
g(std::forward<T>(param)); // perfect forward to g
}
Run Code Online (Sandbox Code Playgroud)
这param是一个lvalue,并std::forward最终将它转换为右值或左值,具体取决于与它有关的参数.
看一下cppreference.com的定义,std::forward我发现还有一个rvalue重载
template< class T >
T&& forward( typename std::remove_reference<T>::type&& t );
Run Code Online (Sandbox Code Playgroud)
任何人都可以给我任何rvalue超载的理由吗?我看不到任何用例.如果你想将一个右值传递给一个函数,你可以按原样传递它,不需要std::forward在它上面应用.
这与std::move我不同,我明白为什么人们也想要一个rvalue重载:你可能会处理通用代码,在这些代码中你不知道你传递了什么,你想要无条件支持移动语义,请参阅例如为什么std ::移动采取普遍参考?.
c++ ×10
rvalue-reference ×10
c++11 ×9
rvalue ×2
constructor ×1
d ×1
return ×1
scope ×1
std ×1
visual-c++ ×1