我为什么要或不应该创建我的所有函数和成员函数来取一个带有a的rvalue版本lvalue?你总是可以转发lvalue到右转,对吧?我甚至可以拥有const rvalue,为什么这是一个坏主意或好主意呢?
我在代码中的意思如下.该"&&" rvalue引用允许用户使用临时对象,并且仍然可以lvalue通过简单的转发使用.所以考虑到这一点,我为什么要提供print_string(string& str)(lvalue参考)c ++ 11中的任何函数(除了const参考,因为rvalue有好的)?
#include <iostream>
#include <string>
#include <utility>
using namespace std;
void print_string(string&& str)
{
str += "!!!";
cout << str << endl;
}
void print_string2(string& str)
{
str += "???";
cout << str << endl;
}
int main(int argc, char* argv[])
{
print_string("hi there"); // works
print_string(string("hi again")); // works
string lvalue("lvalue");
print_string(forward<string>(lvalue)); // works as expected
//print_string(lvalue); // compile error
//print_string2("hi there"); // comile error
//print_string2(string("hi again")); // compile error
print_string2(lvalue);
char a;
cin >> a;
}
Run Code Online (Sandbox Code Playgroud)
嗨,您好!!!
你好,我们又见面了!!!
左值!
左值!!! ???
void print_string(string&& str)提供了一个更灵活的用例void print_string2(string& str),为什么我们不应该一直使用rvalue参数呢?
与C++的许多功能一样,有一个如何使用左值和右值引用的约定.
为惯例另一示例是运营商,尤其是==和!=.您可以重载它们以返回doubles,并复制文件以进行比较.但按照惯例,它们返回bool并且只比较左右操作数而不进行修改.
rvalue引用的约定是它们引用资源可能被"窃取"的对象:
引入了Rvalue引用以支持移动语义,即资源所有权的转移.移动语义通常意味着可以移动绑定到右值引用的对象.从传统上移动的对象被假定为处于有效但未知的状态.例如:
// returns a string that equals i appended to p
string join(string&& p, int i); // string&& means: I do something to p. Or not.
// append i to p
void append(string& p, int i);
string my_string = "hello, world."; // length is 13
append(my_string, 42); // I know what state my_string is specified to be in now
my_string[12] = "!"; // guaranteed to work
string result = join( std::move(my_string), 42 );
// what state is my_string now in?
char c = my_string[1]; // is this still guaranteed to work?
string const cresult = join("hello, number ", 5);
// fine, I don't care what state the temporary is in -- it's already destroyed
Run Code Online (Sandbox Code Playgroud)
人们可以想到如下定义:
string join(string&& p, int i)
{ return std::move(p) + std::to_string(i); }
void append(string& p, int i)
{ p += std::to_string(i); }
Run Code Online (Sandbox Code Playgroud)
这个定义join确实会从中窃取资源p,而标准实际上并没有指定p操作后的状态std::move(p) + std::to_int(i)(这会创建一个从中窃取资源的临时状态p).
对于这个简单的例子,您仍然可以使用
string result = "hello ";
result = join(std::move(result), 42);
Run Code Online (Sandbox Code Playgroud)
"替换" append.但是移动也可能很昂贵(它们总是复制某些东西),并且这种技术不能轻易替换多个左值参考参数.
在我看来,你应该在函数的名称中指出它是否需要左值引用并修改参数.我当然不希望命名的函数print_string2修改我传入的字符串.
恕我直言,移动对象处于一个有效但未指定状态的惯例,应该阻止你在任何地方使用右值引用.
此外,与使用就地操作相比,使用太多移动可能会对性能产生轻微影响join.
各种stackexchange问题已帮助我回答了自己的问题。
我向前走,感到困惑。这个答案很有帮助(我通常可以/总是使用std :: forward而不是std :: move吗?)您可以r / forward / move / g,但我的问题仍然相同。请务必直接阅读Scott Meyer对这个问题的回答:http : //scottmeyers.blogspot.co.uk/2012/11/on-superfluousness-of-stdmove.html
那是个好主意吗?好了,这些帖子帮助我弄清楚了:在C ++ 11中,按值传递是否是合理的默认值?
和
是否应该将C ++ 11中的所有/大多数设置器函数编写为接受通用引用的函数模板?
和
| 归档时间: |
|
| 查看次数: |
1878 次 |
| 最近记录: |