经过几年没有触及c ++,我回过头来决定再次学习使用教科书(“Sutherland,Bruce。学习C ++进行游戏开发(第59页).Apress.Kindle Edition。”)。 我有两个简单的问题:
1) 在一个示例中,本书使用以下代码行来调用函数:
string playerInput;
GetPlayerInput( playerInput);
函数本身定义为:
void GetPlayerInput(string& playerInput)
{
cin >> playerInput;
}
问题:“playerInput”作为“string&”传递。真的有必要吗?当我们可以让函数返回一个字符串并按照这样的方式执行时,为什么将它作为引用传递:
string playerInput;
playerInput = GetPlayerInput();
和
string GetPlayerInput()
{
cin >> playerInput;
return playerInput;
}
这只是一种风格选择还是我在这里遗漏了什么?
2)获取用户名的类访问器方法定义为:
'void SetName(const std::string& name);'
没有其他解释。这个“常量”的东西怎么了?我做了一些研究,但只是更加困惑。为什么在将字符串作为参数传递时(并再次作为参考?)
需要它非常感谢您的帮助!
答案 0 :(得分:1)
1)原则上,按价值返回涉及一份副本。然而,即使在调试模式下,几乎所有编译器都会执行RVO / NRVO。
所以一般来说它是一个API选择,但如果在循环中使用它可能很重要。比较两者,例如:
for (;;) {
string playerInput = GetPlayerInput();
if (playerInput.empty()) break;
// do something with the playerInput
}
string playerInput;
for (;;) {
GetPlayerInput(playerInput);
if (playerInput.empty()) break;
// do something with the playerInput
}
有一个微妙的区别,这使得后一种情况更具性能。在第一种情况下,即使使用NRVO,每次都会重新分配字符串。在第二种情况下,相反,字符串仅被分配/重新分配几次,最后它具有最长输入的大小。
此外,GetPlayerInput
可以返回bool
,这样可以让循环更好看:
string playerInput;
while (GetPlayerInput(playerInput)) {
// do something with the playerInput
}
2)通过const ref传递(与非const ref相反)不仅使得无法错误地修改参数,而且还可以使用 temporaries ,这可以说是偶数更重要。举个例子:
setName("Some name");
不适用于非const引用。
当通过值传递时,还会涉及到一个副本 - 它可能被省略(在C ++中允许这样做,它的缺点是依赖于复制的代码可能不起作用),但是不能保证(并且仅在通过临时工具。)。
建议使用pass by value的唯一情况是,无论如何都要在内部复制参数,例如:
SomeClass operator +(SomeClass a, const SomeClass& b) {
return a += b;
}
与
相反SomeClass operator +(const SomeClass& a, const SomeClass& b) {
SomeClass result = a;
return result += b;
}
答案 1 :(得分:0)
完全取决于程序员是通过引用还是通过值传递。如果您正在讨论通过引用传递,则更改将在变量的原始值中进行,而如果使用传递值,则将实际参数的副本传递给被调用函数的形式参数。所以,你可以做到这两点!