C++ 存储持续性,作用域和链接性

C 语言常用小点
C字符串
C 基础-指针,函数处理器
C 文件操作
JNI 基础 C语言版

C++ 基础知识点大纲

[C++ 基础经验知识点]
C++ 基础代码模板和使用
C++ 基础-定点模式
C++ 宏定义
C++ 指针区分
C++ 指针特别篇-指针转换和智能指针
C++ 类的继承和多继承
C++ this 原理
C++浅拷贝和深拷贝的原理
C++ 函数
C++ 仿函数
C++ 友元函数理解
C++ STL
C++ 模板函数纯虚函数和Java对比
C++ 函数运算符重载(二)化简版
C++ 多线程
C++ 算法包和源码简析
C++ 存储持续性,作用域和链接性

自动存储,执行完代码内存自动释放,生命周期由程序控制。 生命周期短再方法等大括号内(代码块内)
静态存储持续性: static定义,函数外部定义,整个程序结束生命周期结束
线程存储持续性: thread_local
动态存储持续性: new 分配 delete释放。 由人工控制。

代码块作用域

#include <iostream>
using namespace std;
int main()
{
    int teledeli = 5;
    {
        int teledeli = 20;
        int weight = 30;
        cout << "teledeli:" << teledeli << endl;
        cout << "weight:" << weight << endl;
    }
    cout << "teledeli out:" << teledeli << endl;
    return 0;
}

结构体和类类似,方法可以定义在结构体中

#include <iostream>
using namespace std;
struct Stock
{
    int a;
    void show(const Stock &s)
    {
        cout << s.a << endl;
    }
};

int main()
{
    Stock s;
    s.a = 100;
    s.show(s);
    return 0;
}

外部变量,就是文件内函数外面的变量
static 存储在堆生命周期是整个程序

#include <iostream>
using namespace std;
int c = 30;
static int b = 20;

int main1()
{
    {
        static int a = 10;
        cout << a << endl;

    }
   cout << b << endl;
   cout << c << endl;
}

在多文件程序中,可以在一个文件(且只能在一个文件)中定义一个外部变量。使用该变量的其他文件必须使用关键字extern声明它

统计输入字符的个数

#include <iostream>
using namespace std;
void strcount(const char *str);

const int ArSize = 10;
// int total = 0;
int main()
{
    char input[ArSize];
    char next;
    cin.get(input, ArSize);
    while (cin)
    {
        cin.get(next);
        while (next != '\n')
        {
            cin.get(next);
        }
        strcount(input);

        cin.get(input, ArSize);
    }
    return 0;
}
void strcount(const char *str)
{
    int count = 0;
    static int total = 0;

    cout << "\"" << str << "\" contains ";
    while (*str++)
    {
        count++;
    }
    total += count;
    cout << "total: " << total << endl;
    cout << "count: " << count << endl;
}

两个文件中,全局限定变量和static 内部限定变量区别(链接性)
file1

#include <iostream>
using namespace std;

int tom = 3; // 全局外部变量
int disc = 30;
static int harry = 300; // 全局内部变量
void remote_accessx();
int main()
{
    cout << "tom = " << tom << " in &tom  " << &tom << endl;
    cout << " disc = " << disc << " in &disc " << &disc << endl;
    cout << " harry = " << harry << " in &harry " << &harry << endl;
    remote_accessx();
    return 0;
}

file2


#include <iostream>

using namespace std;
extern int tom;
static int disc = 10;
int harry = 1000;


void remote_accessx()
{
    cout << "tom = " << tom << " in &tom  " << &tom << endl;
    cout << " disc = " << disc << " in &disc " << &disc << endl;
    cout << " harry = " << harry << " in &harry " << &harry << endl;
}

说明符和限定符
auto register static extern thread_local mutable

  1. cv-限定符
  • const
  • volatile:代码没有对内存单元修改,它的值也可能发生变化
    编译器会有自己的优化过程
  1. mutable
    结构(或者类)变量为const 其成员变量也可以修改。
struct data{
char name[10]; 
mutable int access;
}

如果,const data veep ; veep.name 不可以重新修改,veep.access 却可以修改

  1. const
    const 修饰的变量,不会影响变量声明周期。变量声明周期不会改变。const的外置变量限定在了当前文件中。
    比如:文件1:const int test = 10; 通过inclue 等 文件2: const int test = 30; 互不影响。extern const int test = 10;后,升级为外部变量,但是不能再给test进行修改,可以extern const int test ;这个时候这个test == 10

函数和链接性

函数内部是不能在此定义函数。默认函数的链接是外部的。
也可以用extern 声明,证明在外部是有函数定义的。(所以可以省略)
用static 定义函数,那么在其他文件中用 static 也可以定义同样函数,那么限定为文件内部,外部看不见。

static 声明函数是内部,只能在当前文件查找,我们做一个实验

file1

#include <iostream>
using namespace std;
static void remote_access();
void remote_access();

int main()
{

    cout << "main access" << endl;

    remote_access();

    return 0;
}

void remote_access()
{
    cout << "remote_access 1" << endl;
}

file2

#include <iostream>
using namespace std;

static void remote_access()
{
    cout << "remote_access 2" << endl;
}
void remote_access();

不同平台,不同编译器对顺序要求不同。但是思想是一样。

存储方案和动态分配

  1. new/delete/malloc()
  2. float *p = new float[20]
    extern float *p = new float[20]
  3. int *p = new int(6);
    int *pi = new int;
    double *pd = new double(99.9);
    int * ar = new int[4]{2,3,4,5};
  4. new/new [] /delete/delete []

char buffer1[20];
char buffer2[500];
Struct_custom *p2 = new (buffer1) Struct_custom;
int *p4 =new (buffer2)int[20];

new 负责在堆找到足够满足要求的内存块


#include <iostream>
using namespace std;
const int BUF = 512;
char buffer[BUF];
const int N = 5;
int main()
{

    cout << "buffer[BUF] address at:" << &buffer << endl;


    double *pd1, *pd2;
    int i;
    cout << "Calling new and palcement new\n";
    pd1 = new double[N];
    pd2 = new (buffer) double[N];
    for (i = 0; i < N; i++)
    {
        pd2[i] = pd1[i] = 1000 + 2.0 * i;
    }
    cout << "Memory addresses:\n"
         << " heap:" << pd1 << " static:" << (void *)buffer << endl;
    cout << "Memory content:\n";
    for (i = 0; i < N; i++)
    {
        cout << pd1[i] << " at" << &pd1[i] << ";";
        cout << pd2[i] << " at" << &pd2[i] << endl;
    }
    cout << "\n Calling new and palcement new a second time:\n";
    double *pd3, *pd4;
    pd3 = new double[N];
    pd4 = new (buffer) double[N];
    for (i = 0; i < N; i++)
    {
        pd4[i] = pd3[i] = 1000 + 4.0 * i;
    }
    cout << "Memory content:\n";
    for (i = 0; i < N; i++)
    {
        cout << pd3[i] << " at" << &pd3[i] << ";";
        cout << pd4[i] << " at" << &pd4[i] << endl;
    }
    cout << "\n Calling new and palcement new a third time:\n";
    delete[] pd1;
    pd1 = new double[N];
    pd2 = new (buffer + N * sizeof(double))double[N];
    for (i = 0; i < N; i++)
    {
        pd2[i] = pd1[i] = 1000 + 2.0 * i;
    }
   
    cout << "Memory content:\n";
    for (i = 0; i < N; i++)
    {
        cout << pd1[i] << " at" << &pd1[i] << ";";
        cout << pd2[i] << " at" << &pd2[i] << endl;
    }
    return 0;
}

打印后buffer 的存储地址收地址,和new出来的地址是同一个块是个静态地址,new double是动态的。

名称空间

#include <iostream>
using namespace std;
double pail;
namespace David
{
    double pail;
    void fetch();
}

namespace Lucy
{
    double pail;
    void fetch();
}

int main()
{    
    pail = 10;
    Lucy::pail = 20;
    cout << David::pail << Lucy::pail << endl;
    return 0;
}
  1. using namespace David;
  2. using David::pail;
  3. David::pail;

Namespace.h

#include <iostream>
#include <string>
namespace pers
{
    struct Person
    {
        std::string fname;
        std::string lname;
    };
    void getPerson(Person &rp);
    void showPersion(const Person &rp);
}

namespace debts
{
    using namespace pers;
    struct Debt
    {
        Person name;
        double amount;
    };
    void getDebts(Debt &rd);
    void showDebt(const Debt &rd);
    double sumDebts(Debt *ar, int n);

}

Namespace.cpp

#include <iostream>
#include "Namespace.h"
namespace pers
{
    using std::cin;
    using std::cout;
    void getPerson(Person & rp)
    {
        cout << "Enter first name: ";
        cin >> rp.fname;
        cout << "Enter last name: ";
        cin >> rp.lname;
    }
    void showPersion(const Person& rp)
    {
        cout << rp.lname << ", " << rp.fname;
    }
}

namespace debts
{
    void getDebts(Debt & rd)
    {
        getPerson(rd.name);
        cout << "Enter debt: ";
        cin >> rd.amount;
    }
    void showDebt(const Debt& rd)
    {
        showPersion(rd.name);
        cout << "  Debt is:$ " << rd.amount << std::endl;
    }
    double sumDebts(Debt * ar,int n) 
    {
        int total = 0;
        for (int i = 0; i < n; i++)
        {
            total += ar[i].amount;
            showPersion(ar[i].name);
            showDebt(ar[i]);
        }

        return total;
        

    }
}

UseNamespace.cpp

#include <iostream>
#include "Namespace.h"
void other();
void another();
int main()
{
    using debts::Debt;
    Debt golf = {
        "Banny", "Goatsniff", 120.0

    };

    showDebt(golf);
    other();
    another();
}

void another()
{
    using pers::Person;
    Person collector ={"Milo","Rightshift"};
    showPersion(collector);
    std::cout << std::endl;
}

void other()
{
    using std::cout;
    using std::endl;
    using namespace debts;
    Person dg = {"Doodles", "Glister"};
    showPersion(dg);

    Debt zipply[3];
    int i;
    for (i = 0; i < 3; i++)
    {
        getDebts(zipply[i]);
    }
    for (i = 0; i < 3; i++)
    {
        showDebt(zipply[i]);
    }
    cout << "total debt: $" << sumDebts(zipply, 3) << endl;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容