C++中static用法
本文为个人学习笔记,参考《C++ Primer(中文第五版)》和《王道程序员求职宝典》
本文分为两个部分:不考虑类、类中static的作用
一、不考虑类,static的作用
1、对其他文件隐藏
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都有全局可见性。同时编译两个源文件:a.cpp和main.cpp,在a.cpp中有以下内容:
#include<cstdio> char a='A'; //全局变量
void msg() printf("Hello\n");
则在a.cpp中定义的全局变量a和函数msg能在main.cpp中使用。这是因为未加static前缀的全局变量都具有全局可见性,其他源文件也能访问。若加了static,就会对其他源文件隐藏了。如在a和msg的定义前加上static,main.cpp就不能访问了。
这样可以在不同的文件中定义同名函数和同名变量,而不用担心命名冲突。
2、static的第二作用是默认初始化为0。
包括未初始化的全局静态变量和局部静态变量。另外未初始化的全局变量也具备之一属性,因为为初始化的全局变量与未初始化的静态变量存储在同一区域内(BSS,全局(静态)存储区,BSS的特点是在程序执行之前BSS会自动清0)。
3、static的第三个作用是保持局部变量内容的持久。
函数内的局部变量,当调用时就存在,退出函数时就销毁,但静态局部变量虽然在函数内定义,但静态局部变量始终存在,也就是说它的生存期为整个源程序,其特点是只进行一次初始化且具有“记忆性”。
值得注意的是:虽然局部静态变量的生存周期为整个源程序,但其作用域仍与局部变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量嗨继续存在,但不能使用它了。
#include<iostream>
#include<cstddef> using namespace std; size_t count_call()
{
static size_t ctr = ;
return ++ctr;
} int main()
{
for (size_t i = ; i != ; ++i)
{
cout << count_call() << " ";
}
/*未加下一行之前输出1到10,加了之后显示出错:未声明的标识符ctr*/
//cout << ctr << endl; return ;
}
二、类中static的作用
有时候类需要它的一些成员与类本身直接相关,而不是与类的各个对象保持关联,我们可以通过在成员的声明之前加上关键字static使得其与类关联在一起。即,表示属于一个类而不是属于此类的任何特定对象的变量和函数。
类的静态成员存在任何对象之外,对象中不包含任何与静态成员函数有关的数据。和其他成员一样,静态成员可以是public的或private的。什么意思了?下面结合例子我们分静态数据成员和静态成员函数来说
class Account
{
public:
void calculate() {amount+=amount*interestRate;}
static double rate() {return interestRate;}
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
}
1、静态数据成员
通常,非static数据成员存在与类类型的每个对象中,而static数据成员独立与该类的任意对象而存在,即每个static数据成员是与类关联的对象,并不是与该类的对象相关联,通俗讲,静态数据成员不属于类的任一对象。也就是说,当某个类的实例修改了该静态成员变量,其修改值为该类的其他所有实例所见。
(1)静态数据成员定义
因为静态数据成员不属于类的任一对象,所以它们并不是创建类对象时被定义,这意味着不是有类的构造函数初始化。一般来说,static数据成员要在类定义体的外部定义,和其他对象一样,一个静态数据成员只能定义一次。另外,静态数据成语定义在任何函数之外,因为一旦它被定义,就将一直存在于程序的整个生命周期。通俗点讲,对静态数据成员就是不能在类中定义,要类似全局变量一样,单独定义。(有一种例外,见下)
/*定义并初始化一个静态成员*/
double Account::interestTrate=initRate();
(2)静态成员的类中初始化
通常情况下,类的static成员(数据和函数)不应该在类的内部初始化,然而我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须是字面值常量类型的constexpr。
Tip:要想确保对象只定义一次,最好的办法是吧静态数据成员的定义与其他非内联函数的定义放在同一个文件中。
2、静态成员函数
因为普通的成员函数总是具体的属于某个类的具体对象,所以普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身。但是静态成员函数由于不予任何的对象相关联,因此它不具有this指针。因而无法访问类对象的非静态成员函数,也无法访问静态成员函数,只能调用其余的静态成员函数与访问静态数据成员。另外,因为static成员不是任何对象的组成部分,所以static成员函数不能被声明为const。
(1)静态类成员函数既可以定义在类的内部可以在内的外部,当定义在类的外部是,不能重复使用static关键字,该关键字只能出现在类内部的声明语句中。
void Account::rate(double newRate)
{
interestRate=newRate;
}
另外,static成员函数也不能被声明为虚函数、volatile。
(2)静态成员函数可以总结为:
a)静态成员之间可以相互访问,包括静态成员函数访问静态数据和访问静态数据函数。静态成员函数不能访问非静态成员函数和非静态数据成员,非静态成员函数可以任意地访问静态成员函数和静态数据成员。
b)由于没有this指针额外开销,因此静态成员函数与类的非静态成员函数相比速度上会有少许增加。
三、静态成员和普通成员对比
静态成员和普通成员的一个区别是,我们可以使用静态成员作为默认实参:
class Screen
{
public:
/*bkground表示一个在类中稍后定义的静态成员*/
Screen &clean(char=bkground);
private:
static const char bkground;
};
非静态数据成员不能作为默认实参,因为它的值本身属于对象的一部分。
C++中static用法的更多相关文章
- c/c++中static用法总结
static的作用主要有两种: 第一个作用是限定作用域:第二个作用是保持变量内容持久化: c语言中static的用法: 1.全局静态变量: 用法:在全局变量前加上关键字static,全局变量就定义成一 ...
- C++中static用法总结
1用于局部变量 C++中局部变量有三种: (1)auto:此关键词常常省略.auto type a 常常简写为type a. 如: int a=auto int a 存储在内存的栈中,只在此局部区域有 ...
- C/C++中static关键字的用法
1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...
- C/C++中static的用法全局变量与局部变量
1.什么是static? static 是C/C++中很常用的修饰符,它被用来控制变量的存储方式和可见性. 1.1static的引入 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它 ...
- C++ 中 static 与 const 的用法及对比
在这个学习过程中我对 static 及 const 的使用时常会混淆,因此整理,加深记忆 一.类的静态成员 如果某个属性为整个类所共有,不属于任何一个具体对象,则采用 static 关键字来声明静态成 ...
- Java中static的用法,初始化块
使用 Arrays 类操作 Java 中的数组语法: Arrays.sort(数组名); 可以使用 sort( ) 方法实现对数组的排序,只要将数组名放在 sort( ) 方法的括号中,就可以完成对该 ...
- C++和Java中的静态Static用法
C++和Java中都有的一个静态关键字Static,可以放在类中的变量或者函数之前,就成了静态变量或者静态函数. 静态变量又分为静态全局变量和静态局部变量,可参见网上大神总结的C++全局变量,局部变量 ...
- Java类中static的用法
关于Java中static的使用有以下四种情况: 1.静态成员变量 被static修饰的成员变量,叫静态成员变量或类变量:没有被static修饰的变量,叫实例变量. 两者的区别是: ...
- C++中static数据成员详解
本文和大家分享的主要是c++中static数据成员的相关用法及源码示例,希望能帮助大家更好的学习C++. static(静态存储)数据成员 StaticTest.cpp : 定义控制台应用程序 ...
随机推荐
- MongoDB之我是怎么成为Primary节点的
此文已由作者温正湖授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Primary(主)是MongoDB复制集中的最重要的角色,是能够接受客户端/Driver写请求的节点,(读 ...
- 低于0.01%的极致Crash率是怎么做到的?
WeTest 导读 看似系统Bug的Crash 99%都不是系统问题!本文将与你一起探索Crash分析的科学方法. 在移动互联网闯荡多年的iOS手机管家,经过不断迭代创新,已经涵盖了隐私(加密相册). ...
- katalon系列七:Katalon Studio全局变量
假如你有3个脚本都用到了用户名,如果是写死在脚本中,那么需要改变的时候,你需要修改3个地方,我们可以把用户名设为全局变量,在3个脚本中引用,需要修改时只要修改全局变量中的用户名值即可. 在Katalo ...
- jenkins配置git+maven+Publish over SSH
一.配置git 1.新建项目,源码管理选择git 2.Repository URL输入git目录 3.Credentials中选择新增凭据,凭据类型选择SSH,usename输入git,passphr ...
- python中出现ascii编码问题的解决办法
一劳永逸,一次性全盘解决的办法 环境变量中去设置 以centos 7为例: vim /etc/profile export PYTHONIOENCODING=utf-8 source /etc/pro ...
- avalonJS入门
前端神器avalonJS入门(一) posted @ 2014-10-31 17:44 vajoy 阅读(8759) 评论(42) 编辑 收藏 avalonJS是司徒正美开发和维护的前端mvvm框 ...
- BAT 批处理脚本 教程 【转】
BAT 批处理脚本 教程 第一章 批处理基础 第一节 常用批处理内部命令简介 批处理定义:顾名思义,批处理文件是将一系列命令按一定的顺序集合为一个可执行的文本文件,其扩展名为BAT或者CMD.这些命令 ...
- SGU 520 Fire in the Country(博弈+搜索)
Description This summer's heat wave and drought unleashed devastating wildfires all across the Earth ...
- iconFont 阿里巴巴矢量图标使用方法
挑选图标的过程(共6步) 进入网站:Iconfont网址:http://www.iconfont.cn 点击网站上方的“官方图标库”,选择自己喜欢的图标.在这里我选择天猫的图标库. 选择好自己喜欢的图 ...
- 采用c#实现功能1
看了好多c#的菜鸟教程不如自己开始动手打代码,最终实现了功能一,参考了网上的wordcount代码发现无论是c++还是c#大部分采用的是哈希表的方法实现的,本来还想仅用循环实现遍历句子中的所有字符,即 ...