第6章 Constant, Static and Name Space

news2024/11/26 12:44:22

Const

• declares a variable to have a constant value

const int x = 123; 

x = 27; // illegal! 

x++; // illegal! 

int y = x; // Ok, copy const to non-const 

y = x; // Ok, same thing 

const int z = y; // ok, const is safer

变量variable

常量 constant ,值不会发生变化的变量,如被const修饰的x

字面量 literal ,如整数123

Constants

• Constants are variables

– Observe scoping rules

– Declared with “const” type modifier

• A const in C++ defaults to internal linkage

– the compiler tries to avoid creating storage for a const --  holds the value in its symbol table.

– extern forces storage to be allocated

Compile time constants

const int bufsize = 1024; 

• value must be initialized 

• unless you make an explicit extern declaration:

extern const int bufsize; 

• Compiler won't let you change it

• Compile time constants are entries in compiler symbol  table, not really variables.

Run-time constants

• const value can be exploited

const int class_size = 12;  编译时常量

int finalGrade[class_size]; // ok 

int x; 

cin >> x; 

const int size = x; 

double classAverage[size]; // error! c++98是错的,不能用变量作为数组大小,c++11才对

Aggregates

• It’s possible to use const for aggregates, but storage will  be allocated. In these situations, const means “a piece of  storage that cannot be changed.

• However, the value  cannot be used at compile time because the compiler is  not required to know the contents of the storage at compile  time. 

const int i[] = { 1, 2, 3, 4 };  数组元素不能修改

float f[i[3]]; // Illegal  c++98标准,const变量不能做其他数组大小

struct S { int i, j; }; 

const S s[] = { { 1, 2 }, { 3, 4 } }; 

double d[s[1].j]; // Illegal

Pointers and const

• char * const q = "abc"; //     q is const 

*q = 'c'; // OK 

q++; // ERROR 

• const char *p = "ABCD";  // (*p) is a const char 

*p = 'b'; // ERROR! (*p) is the const

Quiz: What do these mean?

string p1( “Fred" ); 

const string* p = &p1;  //对象不能改

string const* p = &p1;  //对象不能改

string *const p = &p1; //指针不能改

const在*之前说明对象不能不能改,在*后面表示指针不能改

Pointers and constants

Remember:

 *ip = 54; // always legal since ip points to int

 *cip = 54; // never legal since cip points to const int

ip = &ci错误,因为ci可能被*ip修改

cip = &ci正确,是因为cip指针不能修改对象,所以ci不会被修改,安全

String Literals

char* s = "Hello, world!";

• s is a pointer initialized to point to a string constant

• This is actually a const char* s but compiler accepts it  without the const

• Don't try and change the character values (it is undefined  behavior)

• If you want to change the string, put it in an array:

char s[] = "Hello, world!";

int main(){
  char* s = "abc";
  char a[] = "abc";
  printf("s=%p\n", s);
  printf("a=%p\n", a);
}
/*
输出:
s=0x103f41f9e  地址比a小
a=0x7ff7bbfc1334
a在栈内,s指向的内存在很小的地方
*/
int main(){
  char* s = "abc";
  char a[] = "abc";
  printf("s=%p\n", s);
  printf("a=%p\n", a);
  s[0] = 'c';
  pringf("1\n");
  a[0] = 'c';
  printf("2\n");
}
/*
s[0] = 'c'报错
*/

Conversions

• Can always treat a non-const value as const

void f(const int* x);

int a = 15; 

f(&a); // ok

const int b = a; 

f(&b); // ok

b = a + 1; // Error!

You cannot treat a constant object as non-constant without an explicit cast 

(const_cast)

Passing by const value?

void f1(const int i) {

i++; // Illegal -- compile-time error 

}

Returning by const value?

int f3() { return 1; } 

const int f4() { return 1; } 

int main() { 

const int j = f3(); // Works fine 

int k = f4(); // But this works fine too! 

}

Passing and returning addresses 

• Passing a whole object may cost you a lot. It is better  to pass by a pointer. But it’s possible for the 

programmer to take it and modify the original value. 

• In fact, whenever you’re passing an address into a  function, you should make it a const if at all possible. 

• Example: ConstPointer.cpp, ConstReturning.cpp

const object

Constant objects

• What if an object is const?

const Currency the_raise(42, 38);对象里的任何一个成员变量都不能被修改

• What members can access the internals?

• How can the object be protected from change? 

• Solution: declare member functions const

– Programmer declares member functions to be safe

Const member functions

• Cannot modify their objects

//不保证不修改,不是保证修改
int Date::set_day(int d){
 //...error check d here...
 day = d; // ok, non-const so can modify
}
//保证不修改成员变量,不会调用非const的成员函数
//因为调用了非const成员函数可能会修改成员变量
int Date::get_day() const { 
  day++; //ERROR modifies data member
  set_day(12); // ERROR calls non-const member
  return day; // ok
 }

Const member function 

• Repeat the const keyword in the definition as well as 

the declaration 声明和定义都要标注const

int get_day () const;

int get_day() const { return day };

• Function members that do not modify data should be 

declared const

• const member functions are safe for const objects

Const objects

• Const and non-const objects

// non-const object
Date when(1,1,2001); // not a const
int day = when.get_day(); // OK
when.set_day(13); // OK
// const object
const Date birthday(12,25,1994); // const
int day = birthday.get_day(); // OK
birthday.set_day(14); // ERROR
class A{
  int i = 0;
public:
  A(int li):i(li){}
int getV() const{return i;}
void setV(int v){i = v;}
};

int main(){
  A a(10);
  const A aa(11);
  a.setV(12);
  cout << aa.getV() << endl;
  aa.setV(13);//报错,不能修改成员变量
}
class A{
  int i = 0;
public:
  A(int li):i(li){}
  int f() const{
    cout << "f() const" << endl;
    reutrn i;
  }
  int f() const{
    cout << "f()" << endl;
    return i;
  }
  void setV(int v){i = v;}
};

int main(){
  A a(10);
  const A aa(11);
  a.setV(12);
  a.f();//调用无const的f()
  aa.f();//调用有const的f()
}
//两个函数构成重载
//int f() const相当于int f(const A* this) const
//int f() 相当于int f(A* this)
//const函数指的是this是const

Constant in class

class A {
  const int i;
};

• has to be initialized in initializer list of the constructor

//当i是const时
//不能用构造函数赋值
A(int x){
  i = x;
}
//可以用初始化列表的方式给i设置初始化值
A(int x): i(x){}

Compile-time constants in  classes

class HasArray {
  const int size;
  int array[size]; // ERROR!
};
//• use "anonymous enum" hack 匿名枚举基础
class HasArray {
  enum { size = 100 };
  int array[size]; // OK!
};
//• Make the const value static:
class HasArray{
  static const int size = 100;//static指所有对象使用同一个变量
  int array[size];
}
//·static indicates only one per class(not one per obeject)

Static

Static in C++

Two basic meanings

• Static storage

–allocated once at a fixed address

• Visibility of a name

• internal linkage

  • Don't use static except inside functions and 

classes.

  • 静态本地变量实际上是特殊的全局变量

  • 它们位于相同的内存区域

  • 静态本地变量具有全局的生存期,函数内的局部作用域

Uses of “static” in C++

Global static hidden in file

C语言规则,File 2编译通过,但链接时extern int s_local报错,因为在File1中属于static,只能在当前文件使用

Static inside functions 

• Value is remembered for entire program

• Initialization occurs only once

• Example: 

–count the number of times the function has been called

void f() {
  static int num_calls = 0;
   ...
  num_calls++;
}

Static applied to objects

• Suppose you have a class 

class X {
  X(int, int);
  ~X();
  ...
};

• And a function with a static X object

void f() {
  static X my_X(10, 20);
   ...
}
class A{
private:
  int i;
public:
  A(int li):i(li){
    cout << "A()" << i << endl;
  }
  ~A(){
    cout << "~A()" << i << endl; 
  }
};
A a(10);
int main(){
  cout << "main()" << endl;
  cout << "end of main()" << endl;
}
/*
输出:
A()10
main()
end of main()
~A()10
全局变量在main之前创建,main之后销毁
*/
class A{
private:
  int i;
public:
  A(int li):i(li){
    cout << "A()" << i << endl;
  }
  ~A(){
    cout << "~A()" << i << endl; 
  }
};
A a(10);

void f(){
  A aa(11);
}
int main(){
  cout << "main()" << endl;
  f();
  cout << "end of main()" << endl;
}
/*
输出:
A()10
main()
A()11
~A()11
end of main()
~A()10
*/

如果f()是static

class A{
private:
  int i;
public:
  A(int li):i(li){
    cout << "A()" << i << endl;
  }
  ~A(){
    cout << "~A()" << i << endl; 
  }
};
A a(10);

void f(){
  static A aa(11);
}
int main(){
  cout << "main()" << endl;
  f();
  cout << "-----" << endl;
  f();
  cout << "end of main()" << endl;
}
/*
输出:
A()10
main()
A()11
--------
end of main()
~A()11
~A()10
第一次调用f()时才构造aa,aa的析构发生在main函数结束,并且第二次调用函数时不会再构造aa
*/

Static applied to objects ...

• Construction occurs when definition is  encountered

–Constructor called at-most once

–The constructor arguments must be satisfied

• Destruction takes place on exit from program

–Compiler assures LIFO order of destructors

Conditional construction

• Example: conditional construction

void f(int x) {
   if (x > 10) {
   static X my_X(x, x * 21);
   ...
}

•my_X

–is constructed once, if f() is ever called with x > 10

–retains its value

–destroyed only if constructed

Global objects

• Consider 

#include "X.h"
X global_x(12, 34);
X global_x2(8, 16);

• Constructors are called before main() is entered

–Order controlled by appearance in file

– In this case, global_x before global_x2

– main() is no longer the first function called

• Destructors called when 

–main() exits

–exit() is called

Static Initialization Dependency

• Order of construction within a file is known

• Order between files is unspecified!

• Problem when non-local static objects in different files 

have dependencies.

• A non-local static object is:

–defined at global or namespace scope

–declared static in a class

–defined static at file scope

x2的构造需要x1,但两个在不同的文件,跨编译单元无法保证构造顺序

Static Initialization Solutions

• Just say no -- avoid non-local static  dependencies.

• Put static object definitions in a single file in correct order.

Can we apply static to members?

• Static means 

–Hidden

–Persistent

• Hidden: A static member is a member

–Obeys usual access rules

• Persistent: Independent of instances

• Static members are class-wide 

–variables or 

–functions

class A{
private:
  int i;
  static int s;
public:
  A(int li):i(li){
    s = 0;
    cout << "A()" << i << endl;
  }
  ~A(){
    cout << "~A()" << i << endl; 
  }
  void setS(int k){s = k;}
  int getS() const{return s;}
  
};

int A::s = 0;//需要写这个定义,因为静态成员变量相当于全局变量,不写出现链接错误,但是定义前面不能写static,因为要在其他的文件使用A类。
int main(){
  A a1(10);
  A a1(20);
  cout << a2,getS() << endl;
  a1.setS(11);
  cout << a2,getS() << endl;
}
/*
输出:
A()10
A()20
0
11 //a2打印s是11。说明静态成员变量在所有对象中共享,实际上是因为静态成员变量属于特殊的全局变量
~A()20
~A()10
*/

静态成员变量在.h的类中声明,一定要注意在.cpp中写定义

Static members

• Static member variables

–Global to all class member functions

–Initialized once, at file scope

–provide a place for this variable and init it in .cpp

–No ‘static’ in .cpp

• Example: StatMem.h, StatMem.cpp

• Static member functions

–Have no implicit receiver ("this") 

• (why?)

–Can access only static member variables 

• (or other globals)

–No ‘static’ in .cpp

–Can’t be dynamically overridden

• Example: StatFun.h, StatFun.cpp

To use static members

• <class name>::<static member>

• <object variable>.<static member>

NameSpace

Controlling names:

• Controlling names through scoping

• We’ve done this kind of name control:

class Marbles {
  enum Colors { Blue, Red, Green };
  ...
};
class Candy {
  enum Colors { Blue, Red, Green };
  ...
};

Avoiding name clashes

• Including duplicate names at global scope is a problem:

// old1.h
void f();
void g();
// old2.h
void f();
void g();

Avoiding name clashes (cont)

• Wrap declarations in namespaces.

// old1.h
namespace old1 {
  void f();
  void g();
}
// old2.h
namespace old2 {
  void f();
  void g();
}

Namespace

• Expresses a logical grouping of classes,  functions, variables, etc.

• A namespace is a scope just like a class

• Preferred when only name encapsulation is 

needed

namespace Math {
   double abs(double );
   double sqrt(double );
   int trunc(double);
   ...
} // Note: No terminating end colon!

Defining namespaces

• Place namespaces in include files:

// Mylib.h
namespace MyLib {
 void foo();
 class Cat {
 public:
   void Meow();
 };
}

Defining namespace functions

• Use normal scoping to implement functions in 

namespaces.

// MyLib.cpp
#include ”MyLib.h”
void MyLib::foo() { cout << "foo\n"; }
void MyLib::Cat::Meow() { cout << "meow\n"; }

Using names from a namespace

• Use scope resolution to qualify names from a namespace.

• Can be tedious and distracting.


#include ”MyLib.h”
void main(){
 MyLib::foo();
 MyLib::Cat c;
 c.Meow();
}

Using-Declarations

• Introduces a local synonym for name

• States in one place where a name comes 

from.

• Eliminates redundant scope qualification:

void main() {
 using MyLib::foo;
 using MyLib::Cat;
 foo();
 Cat c;
 c.Meow();
}

Using-Directives

• Makes all names from a namespace available.

• Can be used as a notational convenience.

void main() {
 using namespace std;
 using namespace MyLib;
 foo();
 Cat c;
 c.Meow();
 cout << “hello” << endl;
}

Ambiguities

• Using-directives may create potential ambiguities.

• Consider:

// Mylib.h
namespace XLib {
 void x();
 void y();
}
namespace YLib {
 void y();
 void z();
}

Ambiguities (cont)

• Using-directives only make the names 

available.

• Ambiguities arise only when you make calls.

• Use scope resolution to resolve.

void main() {
 using namespace XLib;
 using namespace YLib;
 x(); // OK
 y(); // Error: ambiguous
 XLib::y(); // OK, resolves to XLib
 z(); // OK
}

Namespace aliases

• Namespace names that are too short may clash

• names that are too long are hard to work with

• Use aliasing to create workable names

• Aliasing can be used to version libraries.

namespace supercalifragilistic {
 void f();
}
namespace short = supercalifragilistic;
short::f();

Namespace composition

• Compose new namespaces using names from other 

ones.

• Using-declarations can resolve potential clashes.

• Explicitly defined functions take precedence.

namespace first {
 void x();
 void y();
}
namespace second {
 void y();
 void z();
}

namespace mine {
 using namespace first;
 using namespace second;
 using first::y(); // resolve clashes to first::x()
 void mystuff();
 ...
}

Namespace selection

• Compose namespaces by selecting a few 

features from other namespaces.

• Choose only the names you want rather than 

all.

• Changes to “orig” declaration become 

reflected in “mine”.

namespace mine {
 using orig::Cat; // use Cat class from orig
 void x();
 void y();
}

Namespaces are open

• Multiple namespace declarations add to the 

same namespace.

–Namespace can be distributed across multiple files. 

//header1.h
namespace X {
 void f();
}
// header2.h
namespace X {
 void g(); // X how has f() and g();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/578237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python词性标注:一个重要的NLP应用

Python 词性标注&#xff1a;一个重要的 NLP 应用 自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是 AI 领域中的重要分支之一&#xff0c;其可以帮助机器理解和处理人类语言。在 NLP 任务中&#xff0c;词性标注&#xff08;Part-of-Speec…

k8s+负载均衡+防火墙

目录 实验拓扑 实验要求 实验部署 一、kubeadm部署k8s集群 1、环境准备&#xff08;所有节点&#xff09; 2、所有节点安装docker 3、所有节点安装Kubeadm、Kubelet和Kuberctl 4、部署k8s集群 初始化kubeadm 设置kubectl 5、部署网络插件flannel&#xff08;所有节点…

[CSS案例二]—实现一个响应式网页,兼容PC移动端,ScrollReveal 增加动画

大家好&#xff0c;我是小张 本期案例&#xff0c;用前端三件套实现一个简约的响应式布局网页&#xff0c;当屏幕分辨率自适应改变时网页布局会自动发生切换&#xff0c;网页布局同时兼容PC端和移动端&#xff0c; 在普通PC屏幕下网页布局效果 移动端网页布局&#xff1a; 除…

工作需要,JAVAer自学python

人生苦短&#xff0c;我用Python。 是如何学习/自学 Python 的&#xff1f; 我学习python的方式其实很简单很暴力&#xff1a;网上直接搜视频教程&#xff1b; 我之前一直做java的&#xff0c;学习python其实也是一个机缘巧合&#xff1a;当时入职一个朋友刚好有python岗位&a…

初识Unity——基本模型、场景操作、世界坐标系和局部坐标系

目录 基本模型 创建基本模型 基本模型的复制 复杂模型 场景操作 聚焦 旋转 移动 场景视野 世界坐标系 基本介绍 原点 局部坐标系 基本模型 创建基本模型 基本模型的复制 创建基本模型之后&#xff0c;会在我们视野中心生成这个模型&#xff1b;当我们需要复…

SpringAOP简介及实现(包含切面、切点、连接点和通知)

目录 1.什么是AOP、SpringAOP&#xff1f; 2.AOP的组成 3.SpringAOP的实现 4.切点的表达式 1.什么是AOP、SpringAOP&#xff1f; 在学习SpringAOP之前&#xff0c;我们得先了解一下什么是AOP。AOP是一种面向切面编程的思想。那什么是切面呢&#xff1f;它其实是对某一类事情…

软件外包开发代码管理工具

软件代码规范是为了提高代码质量、可读性和可维护性而制定的一系列编程规则和约定。代码管理工具则是用于协助团队成员共享、跟踪和合并代码的工具。今天和大家分享这方面的知识&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&a…

定制底部footer bug:切换tab时position fixed会抖动

文章目录 bug描述position:fixed是啥&#xff1f;有啥用为什么切换tab的时候会抖动如何解决自定义一个InBody组件&#xff0c;将里面所有的元素放到body里面需要放到的底部的内容都放到这个组件里面 bug描述 在element admin里面定制了footer组件&#xff0c;每个页面也可还有…

离散数学_十章-图 ( 3 ):由旧图构造新图

&#x1f4f7;10.3 由旧图构造新图 概念1. 子图2. 真子图3. 导出的子图 旧图构造新图的方法1. 删除或增加图中的边2. 边的收缩3. 删除顶点 有时解决问题只需要图的一部分。 比如我们现在只关心大型计算机网络中涉及济南&#xff0c;广州&#xff0c;深圳的计算机中心&#xff0…

学习c语言中的几道习题(小有难度)!

有兴趣的朋友可以看着题目自己做做&#xff0c;最后在和答案对比&#xff01;相信能力会有所提升的。我现在只是刚刚开始学习c语言&#xff0c;如果有什么说的不对的地方&#xff0c;网路过的大佬&#xff0c;及时予以指正。多谢&#xff01; 1、函数判断闰年 实现函数判断yea…

chatgpt赋能python:Python行太长如何处理?

Python行太长如何处理&#xff1f; 介绍 Python 是一门强大的编程语言&#xff0c;易于学习和使用。它也因其可读性和简洁性而受到广泛赞誉。然而&#xff0c;在实际编写时&#xff0c;往往遇到了行太长的情况。 当一行代码在编辑器中撑满了整个屏幕&#xff0c;或者末尾的字…

【Redis入门篇】| Redis的Java客户端

目录 一&#xff1a; Redis的Java客户端 1. Jedis快速入门 2. Jedis连接池 3. SpringDataRedis快速入门 4. RedisSerializer配置 5. StringRedisTemplate 图书推荐 一&#xff1a; Redis的Java客户端 在Redis官网中提供了各种语言的客户端&#xff0c;地址&#xff1a;…

chatgpt赋能python:Python阶乘算法——快速、高效的算法实现!

Python阶乘算法 —— 快速、高效的算法实现&#xff01; Python作为一门高级编程语言&#xff0c;在众多领域都得到了广泛应用&#xff0c;尤其在算法领域更是拥有着举足轻重的地位。阶乘算法作为计算领域中的一种经典算法&#xff0c;也是Python中不可或缺的一部分。 什么是…

尚硅谷大数据hadoop教程_HDFS

P40 hdfs产生背景和定义 p41 优缺点 p42 组成 p43 文件块大小 p 44 45 shell命令 p46 api环境准备

单链表—C语言实现数据结构

本期带大家一起用C语言实现单链表&#x1f308;&#x1f308;&#x1f308; 文章目录 一、链表的概念&#x1f30e;二、链表中数据元素的构成&#x1f30e; &#x1f30d;三、链表的结构&#x1f30e; &#x1f30d; &#x1f30f;四、 单链表的实现✅✅二、接口的实现✅✅1.单…

SAP-MM-采购申请-价值特性

采购申请审批在维护价值特性时要注意是抬头价值还是行价值&#xff0c;要确定选择哪个&#xff0c;配置时对应配置。 1、创建价值特性CT04 字段名称&#xff1a;CEBAN-GSWRT&#xff0c;和CEBAN-GFWRT 抬头总价值&#xff1a;CEBAN-GFWRT&#xff1b;如果选择的是抬头审批&am…

WPF界面设计

目录 1.设计一个优美的注册界面1.实现效果2.代码展示 2.简易登录按钮设计1.实现效果2.代码展示 3.设计一个优美的注册登录界面&#xff08;连接数据库&#xff09;1.实现效果2.代码展示 4.设计一个简单的在线教育系统界面1.实现效果2.代码展示 5. 设计一个Dashboard1.实现效果2…

linux线程创建等待及退出总结

线程操作 线程操作分线程的创建&#xff0c;退出&#xff0c;等待 3 种 1. 线程创建 #include <pthread.h> int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg); // 返回&#xff1…

chatgpt赋能python:Python中的逆序数

Python中的逆序数 介绍逆序数 在数学中&#xff0c;逆序数指的是一个序列中逆序对的个数。逆序对指一个序列中的两个元素&#xff0c;其中较大的元素在前而较小的元素在后。例如&#xff0c;序列 [2, 4, 1, 3] 中逆序对的个数是 2&#xff1a;(2,1) 和 (4,1)。 逆序数常用于…

chatgpt赋能python:Python逆序遍历-解决问题的神奇方式

Python逆序遍历 - 解决问题的神奇方式 Python是一种简单易学的编程语言&#xff0c;依靠其强大的功能和可扩展性&#xff0c;已成为数据科学、人工智能和Web开发的首选语言之一。Python的核心优点之一是其非常方便的列表操作&#xff0c;而逆序遍历列表是Python的又一个实用而…