我有一个函数可以std::string&就地修改左值引用,返回对输入参数的引用:
std::string& transform(std::string& input)
{
// transform the input string
...
return input;
}
Run Code Online (Sandbox Code Playgroud)
我有一个辅助函数,它允许在右值引用上执行相同的内联转换:
std::string&& transform(std::string&& input)
{
return std::move(transform(input)); // calls the lvalue reference version
}
Run Code Online (Sandbox Code Playgroud)
请注意,它返回一个右值引用.
我已经阅读了关于返回右值引用的SO的几个问题(这里和这里例如),并得出结论这是不好的做法.
根据我的阅读,似乎共识是因为返回值是 rvalues,再加上考虑RVO,只需按值返回就会有效:
std::string transform(std::string&& input)
{
return transform(input); // calls the lvalue reference version
}
Run Code Online (Sandbox Code Playgroud)
但是,我还读到返回函数参数会阻止RVO优化(例如此处和此处)
这使我相信std::string&从左值参考版本transform(...)的std::string返回值到返回值会发生副本.
那是对的吗?
保留我的std::string&& transform(...)版本会更好吗?
考虑以下:
struct vec
{
int v[3];
vec() : v() {};
vec(int x, int y, int z) : v{x,y,z} {};
vec(const vec& that) = default;
vec& operator=(const vec& that) = default;
~vec() = default;
vec& operator+=(const vec& that)
{
v[0] += that.v[0];
v[1] += that.v[1];
v[2] += that.v[2];
return *this;
}
};
vec operator+(const vec& lhs, const vec& rhs)
{
return vec(lhs.v[0] + rhs.v[0], lhs.v[1] + rhs.v[1], lhs.v[2] + rhs.v[2]);
}
vec&& operator+(vec&& lhs, const vec& rhs)
{
return move(lhs += …Run Code Online (Sandbox Code Playgroud) 我正在实现一个构建uint8_t向量的工厂类.我希望能够在返回结果向量时使用移动语义.这似乎有效,但我不相信这是完成我想要的正确方法.
我已经看到了很多关于如何将返回的自动变量视为rvalue并使用调用代码的move构造函数的示例,但在我的示例中,返回的对象是成员.我知道如果调用者将返回值放入移动构造函数中,该成员将丢失其内容 - 这正是我想要的.
我写的是这样的:
#include <cstdint>
#include <iostream>
#include <vector>
class Factory
{
public:
std::vector<uint8_t> _data;
Factory(std::size_t size) :
_data(size, 0)
{
}
void buildContent(int param)
{
// perform operations on the contents of _data
}
std::vector<uint8_t> && data()
{
return std::move(_data);
}
};
int main()
{
Factory factory(42);
factory.buildContent(1);
std::vector<uint8_t> temp(factory.data());
std::cout << "temp has " << temp.size() << " elements" << std::endl;
std::cout << "factory._data has " << factory._data.size() << " elements" << std::endl;
return 0;
} …Run Code Online (Sandbox Code Playgroud) 我有一个非常基本的问题:返回std::vector<A>使用std::move是否是一个好主意?例如:
class A {};
std::vector<A> && func() {
std::vector<A> v;
/* fill v */
return std::move(v);
}
Run Code Online (Sandbox Code Playgroud)
我应该返回std::map,std::list..等等......这样?
我偶然发现了这样的语法:
int&& move(int&& x)
{
return x;
}
Run Code Online (Sandbox Code Playgroud)
据说这就是std::move函数的实现方式,但我不太明白返回类型 (&&) 的实际含义。
我用谷歌搜索了一下,但没有找到答案,有人可以向我解释一下吗?
编辑:
我的大部分困惑来自于函数的返回已经是右值的事实,所以我不明白 && 可以在那里改变什么..不确定我是否有意义。
就在我认为我理解rvalue引用的时候,我遇到了这个问题.代码可能不必要地长,但这个想法很简单.有一个main()函数和returnRValueRef()函数.
#include <iostream>
#define NV(x) "[" << #x << "=" << (x) << "]"
#define log(x) cout << __FILE__ << ":" << __LINE__ << " " << x << endl
using namespace std;
class AClass {
public:
int a_;
AClass() : a_(0) {
log("inside default constructor");
}
AClass(int aa) : a_(aa) {
log("inside constructor");
}
int getInt() const {
return a_;
}
void setInt(int a) {
a_ = a;
}
AClass(AClass const & other) : a_(other.a_) {
log("inside copy constructor"); …Run Code Online (Sandbox Code Playgroud) 我读了标准xvalue.它与rvalue reference表达密切相关.但是在编程时,我真的找不到需要的场景xvalue.
例如:函数myClass&& f()返回一个rvalue reference.所以表达式f()是xvalue.但这有用吗?如何在编程中使用这种技术?
如果myClass g()定义了另一个函数,g()和之间有什么区别f()?
我应该在什么情况下使用f() and xvalue而不是g() prvalue?
在阅读了大量有关右值参考的文章后,我知道:
std::string&& f_wrong()
{
std::string s("hello");
return std::move(s);
}
Run Code Online (Sandbox Code Playgroud)
是错的,并且:
std::string f_right()
{
std::string s("hello");
return s;
}
Run Code Online (Sandbox Code Playgroud)
足以使std::string(或任何移动可构造类)的移动构造函数被调用.此外,如果要使用返回值来构造对象,则应用命名返回值优化(NRVO),该对象将直接在目标地址处构造,因此不会调用移动构造函数:
std::string s = f_right();
Run Code Online (Sandbox Code Playgroud)
我的问题是:何时是通过右值引用返回的好时机?就我所能想到的而言,似乎返回一个右值引用除了像std::move()和之类的函数之外没有意义std::forward().这是真的吗?
谢谢!
c++ rvalue-reference move-semantics return-value-optimization c++11
如果你看一下get辅助函数std::tuple,你会注意到以下的重载:
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&&
get( tuple<Types...>&& t );
Run Code Online (Sandbox Code Playgroud)
换句话说,当输入元组本身是右值引用时,它返回一个右值引用.为什么不按值返回,调用move函数体?我的论点如下:get的返回将被绑定到引用,或者绑定到一个值(它可能被绑定到我想的任何东西,但这不应该是一个常见的用例).如果它与一个值绑定,那么移动构造无论如何都会发生.所以你不会因为价值回归而失去一切.如果绑定到引用,则返回右值引用实际上可能不安全.举个例子:
struct Hello {
Hello() {
std::cerr << "Constructed at : " << this << std::endl;
}
~Hello() {
std::cerr << "Destructed at : " << this << std::endl;
}
double m_double;
};
struct foo {
Hello m_hello;
Hello && get() && { return std::move(m_hello); }
};
int main() {
const Hello & x = foo().get();
std::cerr << x.m_double; …Run Code Online (Sandbox Code Playgroud) Rvalues恕我直言是C++的重大改进,但在开始时似乎很混乱.请看下面的代码:
#include <string>
std::string && foo (void)
{
std::string message ("Hello!");
return std::move (message);
}
void bar (const std::string &message2)
{
if (message2 == "Bye Bye!")
return;
}
int main ()
{
bar (foo ());
}
Run Code Online (Sandbox Code Playgroud)
引用message2是message返回的原始对象的最后一个所有者foo(),对吧?