温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

深入浅析C++中的const

发布时间:2020-11-18 15:16:00 来源:亿速云 阅读:127 作者:Leah 栏目:开发技术

本篇文章给大家分享的是有关深入浅析C++中的const,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

在抽象的最高层次上,const做两件事:

* 一种保护你自己的方式(类似于private)

* 对编译器的一种指示,表明标记为const的对象适合于程序的数据段。换句话说,属于只读数据(ROM-able)。

可以通过例子来看下const的应用。第一个例子中,使用const覆盖了整个例子:

void fun(int i, std::string const & str)
{
 i = 0;     //ok.
 str = "";    //error!
 int const n = 42;
 n = 2;     //error!
}

第二种情况只适用于静态初始化的名称空间-作用域变量(又称全局变量):

int const pi = 3; //ROM-able
std::vector<int> const ivec = {/* ... */}; //Not ROM-able, might allocate.

对声明为const的变量的任何写操作都被显示为未定义行为。这支持const全局变量在ROM中的位置。

如果一个变量定义在ROM中,对它的写操作很可能会使程序崩溃,这取决于平台。如果一个变量不在ROM中,对它的写操作只会改变它的值。这两种情况的结合就是为什么对const变量执行写操作的行为是未定义行为而不是错误。

如果真的需要改写一个const变量的值,可以通过`const_cast`来改写:

void fun(int i, std::string const & str)
{
 i = 0; //ok.
 const_cast<std::string &>(str) = ""; //Also ok (maybe).
}

然而,const_cast并不能避免你在尝试写入声明为const的变量时永远不会遭遇未定义行为的陷阱。

std::string str = "";
fun(0, str); // Ok.
std::string const const_str = "";
fun(0, const_str); // Undefined Behavior!!

因此,只有在确实需要时才使用const_cast,并且只有在知道要写入的底层变量是如何声明的情况下才使用。

**那么,究竟在什么时候什么地方使用const&#63;**

答案就是**Everywhere**。将每个变量声明为const,除非您知道它将被写入。更一般地,在编译器接受的任何地方添加const。

int foo(int arg)
{
 int const x = compute_intermediate_result(arg);
 int const y = compute_other_intermediate_result(x);
 return something_computed_from(x, y);
}

优化器视角下的const

为了优化目的,编译器通常不能使用一致性进行优化。

int get_value(some_class const & x, int const at)
{
 int offset = compute_offset(at);
 return x[offset];
}

此时,在这些函数参数中使用const对优化器没有帮助。x上的const不起作用,因为x已经通过引用传递了。没有x的副本,编译器不知道x是否声明为const。在参数at上的const不能帮助我们,因为at是一个拷贝,它可以以任何方式装入寄存器。
如果编译器可以看到const对象的声明,它有时可以使用其一致性进行优化。

std::vector<int> const vec = { 1, 2, 3 };

int main()
{
 // This may generate code that indexes into vec, or it may generate
 // code that loads an immediate 2.
 return vec[1];
}

如果您想保证这样的优化,您可以在c++11或以后的版本中使用constexpr。使用constexpr声明的变量只对可以静态初始化的类型进行编译,因此,如果编译了它,就会得到一个ROM-able的对象。

constexpr std::array<int, 3> arr = { 1, 2, 3 };

int main()
{
 // This generates code that loads an immediate 2 on every
 // compiler I tried.
 return arr[1];
}

constexpr只处理字面常量类型(literal types)。这些类型与你可能在C中找到的类型相似。任何被声明为const的int或其他整数值都可以像文字一样使用。

void foo(int const arg)
{
 int const size = 2; 

 int array_0[2];  // Ok.
 int array_1[arg]; // Error! arg is a runtime value.
 int array_2[size]; // Ok.
}

静态const类成员

如果声明一个类成员static const,就很像声明一个全局const变量。

int const global_size = 3;

struct my_struct
{
 static int const size = 2;
};

std::array<int, global_size> make_global_array()
{ return {}; }

std::array<int, my_struct::size> make_my_struct_array()
{ return {}; }

但因为这是c++,所以有个问题。如果定义的static const整数值超越界限,则它可能无法被当作字面常量使用,例如一下的例子。

struct my_struct
{
 static int const size;
};

std::array<int, my_struct::size> make_my_struct_array() // Error!
{ return {}; }

int const my_struct::size = 2;

这是的错误时因为编译器在解析foo()时不知道要为my_class::size使用什么值。如果你希望像使用全局const整数值一样使用static const整数值,请始终将它们声明为内联(inline)。

以上就是深入浅析C++中的const,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI