我不明白发生了什么。我只是学习C ++而且我看到了很多这样的东西:
double some_function(const Struct_Name& s) {
...
}
为什么const
如果我们通过引用传递?
答案 0 :(得分:5)
当您不想(或不能)修改传入的参数时,您通过const引用传递,并且您不希望复制对象时可能获得性能损失。
答案 1 :(得分:4)
const
引用可以防止对象被修改,因为const
可能会被修改,但也可以避免复制的潜在成本。
答案 2 :(得分:3)
你告诉编译器,你永远不会改变它。
这使它能够进行一些其他方式无法做到的优化。基本上,它为您提供与传递值相同的语义,但不会导致调用复制构造函数的性能损失。
答案 3 :(得分:2)
const-reference调用避免了Struct_Name
的副本,同时承诺不修改它。
这有一个性能原因和语义原因。
如果Struct_Name
很大,复制它在时间和内存上都很昂贵。
如果Struct_Name
不可复制(或在复制时变为无效),则按值调用是不可能的,或者会引入不合需要的复杂性。例如:std::unique_ptr
和std::auto_ptr
。
答案 4 :(得分:2)
通过使用const
,我们可以发信号通知函数的用户和作为参数s
传递的对象的编译器在函数内部不会被更改(这实际上是可能的,因为我们通过引用传递它!)。如果我们偶然修改对象,编译器可以给我们一个错误,它可以做一些不能做的优化。
另一个优点是,如果函数的调用者只拥有一个指向对象的const
指针,它仍然可以将该对象作为参数提供而不进行强制转换。
答案 5 :(得分:1)
const这里承诺some_function不会修改s参数,
double some_function(const Struct_Name& s) {
...
}
你可以尝试修改它,但编译器会返回错误。实际上,constness要求您仔细编写Struct_Name内部方法,即。你将无法在s对象上调用some_function非const函数。你可以尝试,但你会得到错误。即:
struct Struct_Name {
void myfun() const { } // can be called from some_function
void myfun2() { } // will show error if called from some_function
};
从设计的角度来看,使用const参数是好的,如果你知道某些函数不应该改变你的对象,那么你添加const。这意味着没有其他程序员可以在类层次结构代码中进行深层隐藏的更改,这将修改您的对象。它确实使调试变得容易。
答案 6 :(得分:1)
没有人提到的另一个原因 - 通过const
引用传递允许编译器创建并传递临时对象,而不会生成警告,如果输入值不是参数中声明的确切类型,但是该类型有一个支持传入类型的构造函数。
例如:
void foo(const std::string &s)
{
...
}
foo("hello"); // OK
foo()
期待std::string
,但会收到const char*
。由于std::string
有一个接受const char*
的构造函数,编译器会生成有效执行此操作的代码:
std::string temp("hello");
foo(temp);
编译器知道参数是const
,临时不会被foo()
改变,临时将在foo()
退出后被丢弃,所以它不会抱怨必须创造一个临时的。
如果参数按值(const
或非 - const
传递,无关紧要)而不是通过引用传递相同的事情:
void foo(const std::string s)
{
...
}
void bar(std::string s)
{
...
}
foo("hello"); // OK
bar("world"); // OK
这实际上与此相同:
{
std::string temp1("hello");
foo(temp1);
}
{
std::string temp2("world");
bar(temp2);
}
同样,编译器不会抱怨,因为它知道临时不会影响调用代码,并且bar()
中对临时代码所做的任何更改都将被安全地丢弃。
如果参数是非const
引用,则传递const char*
会生成有关必须创建的临时值的警告,以满足引用绑定。警告是告诉您,当函数退出时,函数对临时(因为它不是const
)所做的任何更改都将丢失,这可能会或可能不会对调用代码产生影响。这通常表明在这种情况下不应使用临时措施:
void foo(std::string &s)
{
...
}
foo("hello"); // warning!