Bar*_*icz 14 c++ string constructor rvalue-reference c++11
我有一个简单的课程:
class X
{
std::string S;
X (const std::string& s) : S(s) { }
};
Run Code Online (Sandbox Code Playgroud)
我最近读过一些关于rvalues的内容,我一直在想,如果我应该编写X
使用rvalue的构造函数,那么我能够检测出std::string
类型的临时对象吗?
我认为应该看起来像:
X (std::string&& s) : S(s) { }
Run Code Online (Sandbox Code Playgroud)
据我所知,在支持C++ 11的编译器中实现std :: string应该在可用时使用它的移动构造函数.
Dav*_*eas 25
X (std::string&& s) : S(s) { }
Run Code Online (Sandbox Code Playgroud)
这不是一个采用rvalue的构造函数,而是一个采用rvalue-reference的构造函数.在这种情况下,您不应该使用rvalue-references.而传值,然后移动到所述构件:
X (std::string s) : S(std::move(s)) { }
Run Code Online (Sandbox Code Playgroud)
经验法则是,如果您需要复制,请在界面中进行复制.
How*_*ant 21
为了澄清:传值的答案没有错.但是string&&
,除了一个细节之外,你的第一个猜测是你没有添加过载:
加:
X (std::string&& s) : S(std::move(s)) { }
Run Code Online (Sandbox Code Playgroud)
即你仍然需要move
因为虽然s
有一个声明类型的右值引用string
,但用于初始化的表达式 是一个类型的左值表达式.s
S
string
实际上,您首先提出的解决方案(添加了移动)比按值传递解决方案略快.但两者都是正确的.当将lvalue和xvalue参数传递给X的构造函数时,pass-by-value解决方案将字符串的移动构造函数调用一个额外的时间.
在lvalue参数的情况下,无论如何都会创建一个副本,而string的复制构造函数可能比string的移动构造函数要昂贵得多(除了适合短字符串缓冲区的字符串,在这种情况下,移动和复制大致相同)速度).
在xvalue参数的情况下(xvalue是已传递给的左值std::move
),按值传递解决方案需要两个移动构造而不是一个.所以它的价格是rvalue参考解决方案的两倍.但仍然非常快.
这篇文章的重点是要明确:按值传递是一种可接受的解决方案.但它不是唯一可接受的解决方案.使用pass-by-rvalue-ref进行重载更快,但缺点是所需的重载次数随着参数N的增长而缩放为2 ^ N.
Ben*_*ley 13
不,你不应该.你应该做的是用这样的一个替换你当前的构造函数:
X (std::string s) :S(std::move(s)) {}
Run Code Online (Sandbox Code Playgroud)
现在你可以处理两个l值,它们将被复制到参数然后移入你的类'字符串,和r值,它们将被移动两次(你的编译器希望可以优化这个额外的工作).
在大多数情况下(有些例外情况我不会在这里讨论),除了你编写的类的移动构造函数之外,你不应该编写带有r值引用的函数.只要您需要自己的值副本,并且这不仅适用于构造函数,您应该按值获取它,并将其移动到需要的位置.您让类自己的移动构造函数根据它是接收r值还是l值来决定是复制还是移动值.毕竟,引入了r值引用,使我们的生活更轻松,而不是更难.
由于您需要参数的副本,请按值获取参数.然后,将其移动到您的会员数据中.它是std::string
构造函数,负责检测给定的参数是左值还是左值,而不是你.
class X
{
std::string s_;
X(std::string s) : s_(std::move(s)) {}
};
Run Code Online (Sandbox Code Playgroud)