为什么要将对象的副本作为函数的参数?为什么const ref不是参数的默认方式?
Why would you ever take the copy of an object as a parameter to your function? Why are not const ref the default way of parameters?
尽管我很喜欢 C++ 编程,但有一件事我真的不明白。对我来说,似乎最常见的函数编程方式是这样的:
some_function(a variable)
do something according to the data in the variable
示例:
bool match_name(const std::string& name)
{
return this->name == name;
}
我发现自己在我的代码中对所有函数参数的 90% 使用了 const ref(也许我做错了什么)。
我的问题是:为什么变量的副本是"default"类型的参数?为什么 const ref 不是默认值?
为什么不是类似的东西?:
void my_function(My_type object) // <- const ref
void my_function(ref My_type object) // <- ref (mutable)
void my_function(copy My_type object) // <- copy
除了历史原因,这将产生非常丑陋的影响。它基本上意味着 MyType myVarName
在函数范围或在函数参数列表中使用时会有不同的含义。
void foo(MyType myVar) //myVar is const ref
{
MyType anotherVar = myVar; // anotherVar is a copy, what?
const MyType& myVarRef = myVar; //a reference, but it looks like it has different type than myVar?
}
想想穷人&
!除非你提出一种不同的方式来区分 refs 和 non-refs,否则你最终会得到
void foo(MyType& myVar) //myVar is a copy?
{
MyType& anotherVar = myVar; // anotherVar is a reference???
}
C++ 具有完善的对象和对象引用概念。后者总是通过在类型中添加 &
来表示。你的提议会把事情搞砸,C++ 会比现在更难理解。
C++ 想要与 C 兼容,并且由于 C 默认使用值语义,因此 C++ 也是如此。按值获取内置类型而按引用获取其他类型是非常不一致的。
但是,通过引用传递并不总是更好。引用导致的指针间接寻址通常会使编译器更难优化代码生成。在许多情况下,按值传递类型仍然比按引用传递更好。这取决于类型。引用的指针间接可能会导致内存读取,而按值传递允许对象在 CPU 寄存器中传递。例如,这样的类型:
class Point {
public:
/* functions */
private:
int x;
int y;
};
应始终按值传递。它只是两个整数。引用可能会导致不必要的内存读取以获取值。
此外,有时即使无法注册类型,您也希望按值传递。由于移动语义,所谓的 "sink functions" 需要存储传递的值,因此对值执行得更好。主要示例是构造器和设置器:
void SomeClass::setString(std::string s)
{
this->s_ = std::move(s);
}
在这种情况下通过引用传递会产生额外的副本。您可以在线阅读更多内容。一个很好的起点是这个 SO 问题:
Are the days of passing const std::string & as a parameter over?
尽管我很喜欢 C++ 编程,但有一件事我真的不明白。对我来说,似乎最常见的函数编程方式是这样的:
some_function(a variable)
do something according to the data in the variable
示例:
bool match_name(const std::string& name)
{
return this->name == name;
}
我发现自己在我的代码中对所有函数参数的 90% 使用了 const ref(也许我做错了什么)。
我的问题是:为什么变量的副本是"default"类型的参数?为什么 const ref 不是默认值?
为什么不是类似的东西?:
void my_function(My_type object) // <- const ref
void my_function(ref My_type object) // <- ref (mutable)
void my_function(copy My_type object) // <- copy
除了历史原因,这将产生非常丑陋的影响。它基本上意味着 MyType myVarName
在函数范围或在函数参数列表中使用时会有不同的含义。
void foo(MyType myVar) //myVar is const ref
{
MyType anotherVar = myVar; // anotherVar is a copy, what?
const MyType& myVarRef = myVar; //a reference, but it looks like it has different type than myVar?
}
想想穷人&
!除非你提出一种不同的方式来区分 refs 和 non-refs,否则你最终会得到
void foo(MyType& myVar) //myVar is a copy?
{
MyType& anotherVar = myVar; // anotherVar is a reference???
}
C++ 具有完善的对象和对象引用概念。后者总是通过在类型中添加 &
来表示。你的提议会把事情搞砸,C++ 会比现在更难理解。
C++ 想要与 C 兼容,并且由于 C 默认使用值语义,因此 C++ 也是如此。按值获取内置类型而按引用获取其他类型是非常不一致的。
但是,通过引用传递并不总是更好。引用导致的指针间接寻址通常会使编译器更难优化代码生成。在许多情况下,按值传递类型仍然比按引用传递更好。这取决于类型。引用的指针间接可能会导致内存读取,而按值传递允许对象在 CPU 寄存器中传递。例如,这样的类型:
class Point {
public:
/* functions */
private:
int x;
int y;
};
应始终按值传递。它只是两个整数。引用可能会导致不必要的内存读取以获取值。
此外,有时即使无法注册类型,您也希望按值传递。由于移动语义,所谓的 "sink functions" 需要存储传递的值,因此对值执行得更好。主要示例是构造器和设置器:
void SomeClass::setString(std::string s)
{
this->s_ = std::move(s);
}
在这种情况下通过引用传递会产生额外的副本。您可以在线阅读更多内容。一个很好的起点是这个 SO 问题:
Are the days of passing const std::string & as a parameter over?