Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 所有C++;函数从现在开始声明为右值?_C++_C++11 - Fatal编程技术网

C++ 所有C++;函数从现在开始声明为右值?

C++ 所有C++;函数从现在开始声明为右值?,c++,c++11,C++,C++11,为什么我应该或不应该创建所有函数和成员函数来接受rvalue,而忽略接受lvalue的版本?您总是可以将左值转发到右值,对吗?我甚至可以使用常量值,为什么这是一个坏主意,还是一个好主意 我在代码中的意思如下。“&&&“rvalue引用允许用户使用临时值,并且仍然可以通过简单的转发使用lvalue。因此,考虑到这一点,我为什么要在c++11中提供任何函数的print_string(string&str)(levaluereference)(除了constreference之外,因为rvalue没有

为什么我应该或不应该创建所有函数和成员函数来接受
rvalue
,而忽略接受
lvalue
的版本?您总是可以将
左值
转发到右值,对吗?我甚至可以使用
常量值
,为什么这是一个坏主意,还是一个好主意

我在代码中的意思如下。
“&&&“rvalue
引用允许用户使用临时值,并且仍然可以通过简单的转发使用
lvalue
。因此,考虑到这一点,我为什么要在c++11中提供任何函数的
print_string(string&str)
levalue
reference)(除了
const
reference之外,因为
rvalue
没有问题)

#包括
#包括
#包括
使用名称空间std;
无效打印字符串(字符串和字符串(&str)
{
str+=“!!!”;

Cuth

和C++的许多特性一样,有一个关于如何使用LValk和RValk引用的约定。 约定的另一个示例是运算符,尤其是

=
!=
。您可以重载它们以返回
双精度
s,并复制文件进行比较。但是按照约定,它们返回
bool
,并且只比较左右操作数而不进行修改


右值引用的约定是,它们引用的对象的资源可能被“窃取”:

  • 左值引用意味着对象为其他人所有
  • 右值引用意味着我们可以从对象中窃取资源
引入右值引用是为了支持移动语义,即资源所有权的转移。移动语义通常意味着绑定到右值引用的对象可以从中移动。从对象中移动通常被假定为处于有效但未知的状态。例如:

// 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
人们可以想到这样的定义:

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);  }
这个
join
的定义确实从
p
中窃取了资源,标准也确实没有指定操作
std::move(p)+std::to_int(i)
p
的状态(它创建了一个从
p
中窃取资源的临时文件)

对于这个简单的示例,您仍然可以使用

string result = "hello ";
result = join(std::move(result), 42);
“替换”
append
。但是移动也可能很昂贵(它们总是复制某些内容),并且多个左值引用参数不容易被这种技术替换

注意:在我看来,当函数接受左值引用并修改参数时,应该在函数名中指明。我当然不希望名为
print\u string2
的函数修改传入的字符串


IMHO,按照惯例,moved from对象处于有效但未指定的状态,这将阻止您在任何地方使用右值引用


此外,当使用过多的移动而不是就地操作时,可能会对性能产生轻微影响。
join
各种stackexchange问题帮助我回答了自己的问题

我对前进和前进感到困惑。这个答案有帮助()你可以r/forward/move/g,我的问题仍然是一样的。请务必直接阅读Scott Meyer对这个问题的回答:

这是个好主意吗?这些帖子帮我弄明白了:


打印字符串2
是一种糟糕的设计。它会修改字符串。例如,有人可能会写:

string s{"hello"};
print_string2(s);     // print the string

foo(s);      // work on the string - oops, it has junk punctuation on it now.
如果函数修改调用方的字符串,则不应调用它

所以你是对的,
string&
string&
好,但这两个选项都是次优的

相反,此函数只能按值接受字符串:

void print_string2(string s)
然后,如果您使用右值(包括xvalues)调用它,参数将移动到
s
,如果您使用左值调用它,则会生成一个副本,这是理想的行为

如果函数不需要修改字符串作为其处理的一部分,则应传递常量引用,该引用可以绑定到右值和左值:

void print_string(const string &s) 
{
在您的示例中,这是最好的选择,因为在打印左值时不需要复制字符串。正文将是:

cout << str << "???" << endl;

cout No!在有意义的地方使用右值(应用
std::move
或提供合理的
std::swap
实现),否则,像往常一样坚持使用
const&
或值传递的参数。您可能会注意到,考虑到新的c++11功能,三的规则可能会变成五的规则。作为一个严格的规则,不应用足够的思想,做一些事情最多是危险的。为正确的工作使用正确的工具。使用r值参考很明显,所管理的资源是可移动的,而使用const l-value ref则说明了这一点。严格的规则:不要停止思考。这会让无数呼叫站点使用
std::foward
/
std::move
,这是愚蠢的。我仍然不明白为什么在所有新功能中,r-value reference是一道闪电这充其量只是一个小功能,是专门为解决两个特定问题而设计的。C++11的99%的新功能更值得了解和使用。如果不链接人们必须通读的内容,你能总结一下你在答案中学到的东西吗?
cout << str << "???" << endl;