繁体   English   中英

const&做什么?

[英]What does const& do?

我不明白发生了什么。 我只是在学习C ++,我看到了很多类似的东西:

double some_function(const Struct_Name& s) {
    ...
}

如果通过引用传递,为什么要使用const

当您不想(或无法)修改传入的参数,并且不希望通过复制对象获得性能下降时,可以通过const引用进行传递。

const引用可以防止对对象进行修改,就像const在其他任何地方一样,而且还可以避免潜在的复制成本。

您告诉编译器您永远不会更改。

这使它能够进行一些其他方面无法做到的优化。 基本上,它为您提供与按值传递相同的语义,但不会招致调用复制构造函数的性能损失。

通过const-reference进行的调用避免了Struct_Name的副本,同时承诺不会对其进行修改。

既有性能原因,也有语义原因。

如果Struct_Name很大,则复制它的时间和内存都非常昂贵。

如果Struct_Name是不可复制的(或在复制时变为无效),则无法通过值调用或引入不希望的复杂性。 例如: std::unique_ptrstd::auto_ptr

通过使用const我们可以向函数用户和编译器发出信号,即作为参数s传递的对象不会在函数内部更改(实际上是可能的,因为我们通过引用传递了它!)。 如果我们无意中修改了对象,则编译器可能会给我们一个错误,并且它可以进行某些优化,否则将无法完成。

另一个优点是,如果函数的调用者仅拥有指向对象的const指针,则它仍可以将该对象作为参数提供而无需强制转换。

此处的const表示some_function不会修改s参数,

double some_function(const Struct_Name& s) {
    ...
}

您可以尝试对其进行修改,但编译器将返回错误。 实际上,constness需要您仔细编写Struct_Name内部方法,即。 您将无法在s对象上的some_function非常量函数内部调用。 您可以尝试,但会出错。 即:

struct Struct_Name {
  void myfun() const { } // can be called from some_function
  void myfun2() { } // will show error if called from some_function
};

从设计的角度来看,使用const参数是好的,如果您知道某些功能不应该更改您的对象,则可以添加const。 这意味着没有其他程序员可以对隐藏在类层次结构代码中的某些内容进行更改,而这些更改将修改您的对象。 这确实使调试变得容易。

没有人提及的另一个原因-如果输入值不是参数中声明的确切类型,但是通过const引用传递,则编译器可以创建并传递临时对象,而不会生成警告,而该类型具有构造函数,支持传入的类型。

例如:

void foo(const std::string &s)
{
    ...
}

foo("hello"); // OK

foo()期望使用std::string但接收到const char* 由于std::string具有接受const char*的构造const char* ,因此编译器会生成有效执行此操作的代码:

std::string temp("hello");
foo(temp);

编译器知道参数为const ,临时变量不会被foo()更改,并且在foo()退出后临时变量将被丢弃,因此它不会抱怨必须创建临时变量。

如果参数是通过值( const或non- 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!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM