C++总结_重复释放内存会导致内存泄漏吗-程序员宅基地

技术标签: c++  

c++和python区别

c++比python多了;把#include替换为import,把{}替换为:python 少了括号,空格方式就按照python来,标准,好看

引用

1.必须初始化
2.不可以更改
3.可以赋值,相当于给原来和引用的值都改变了
4.引用做为函数参数
void swap(int&a,int&b)
{
}
int main(){
int a=0;
int b =1;
swap(a,b)
}可以这样理解:(把实参直接和形参初始化并绑定)
没有形参是引用,主函数直接传的就是引用吗?(应该也是不行的,没见过给引用绑定引用的,牢记一条原则直接变量绑定引用初始化)
主函数传的是引用,形参不是引用肯定不行
5.引用·做函数的返回值
不要返回局部量的引用,因为局部变量在栈区,也就是运行时存储,子程序运行后消亡,而不是整个程序
???????
6.引用的本质
int &ref = a
int *const ref = &a 指针的指向不可动
假使a的地址是0x0011则ref的实际值为0x0011
使用时使用的是*ref(指针是解引用操作)
7.常量引用:
const int&ref = 10
也就是
int 系统中间变量temp = 10;const int& ref = temp

函数

1.函数默认参数
函数默认参数只可以声名和执行发生一次,否则发生二义性2
.2.函数的占位参数
一般写void func(int a,int b)
3.函数重载
首先函数名相同
函数参数个数,函数参数类型,函数参数顺序不同都是重载函数,但是函数返回值不行(调用的时候都可以调用,发生二义性)注意:在使用时,让编译器不知道编译哪个便是发生了二义性
坑:
void func(const int&a)----1
void func (int &a)—2
fun(a)//调用的是1,a是变量
fun(10)//调用1,原因是1不合法,然后const int&a可以直接与10绑定

函数重载默认参数的问题
void fun(int a,itnt b=10)//赋值了的才叫默认参数
void fun(int a)
fun (a)//碰到默认参数发生二义性,因为可以调下边,也可以调上边
fun(a,b)//调下边
注:使用函数重载的时候别用默认参数
4.函数常用模板
无参有反
有参有返
有参无返
无参无反
5.函数分文件编写
创建后缀为.h的头文件
创建.cpp为后缀的源文件
在头文件中写函数的声名(#include
using namespace std;void swap(int a,int b);)
在源文件中写函数的定义(#include “头文件名”void swap(int a,int b){
}
在main.cpp文件中也需要继续添加#include "头文件名“
这样理解:头文件就是为了将分出去的文件和main文件联系起来的东西,所以分出去的文件和main文件都需要加入头这个媒介,也可以说main函数通过头文件找到了swap,头文件通过声名swap找到了具体实现swap,于是就得到了联系,需要注意的是,头文件和所右.cpp文件都只需要在一个项目下即可,而不是要在一个文件夹

指针

1.指针占32位占4字节,64为8字节
2.sizeof()就是得到数据字节大小的
3.指针常量;常量指针(记忆:指针在前是指针是常量, 常量再前的是指针指向的值是常量,在前的重要为常量)
4.数组的名就是指向数组0号元素的地址

结构体

struct student{
}s2;第二种顺便创建结构体变量
int main(){
struct student s1;第一种
}
1.结构体数组
定义结构体
创建结构体数组
给结构体元素中进行赋值
遍历
struct student stuArray[3] = {
{}
{}
{}
}
stuArray【2】即是二号元素
2.结构体指针
struct student a ;
struct student *p = &a
p->name 也就是*p.name
注:就目前来说不管定义结构体还是创建结构体变量都写struct,虽然有的时候不写也是对的
3.结构体嵌套
struct student{
};
struct teacher(
struct student stu;
};
teacher.stdent.name = "王五”
4.结构体做函数参数
void jie_gou_ti(struct student);
void jie_gou_yi(struct *student);
5.const struct #const防止误操作

c++中的内存分区模型

运行前:
1.代码区(共享,只读)
2.全局区(全局变量 const static)
运行后:
3,栈区(变量 编译器管理)
4.堆区(程序员手动开辟手动销毁,new和delete)

类和对象

class Student{
string name =“武凯”;
int m_id = 76;
public:
void print_mes( ){
int name =76;
cout<<name<<this-》name;
}
};
int main (){
Student stu;
stu.print_mes();
return 0;
}
注:在类中如果函数里面没有和类的变量名相同的情况则使用类的对项,否则要使用类的对象需要夹this->
1.类的权限
公共public 成员 类内可以访问 类外可以访问
私有private成员 类内可以访问 类外不可以访问 儿子不可以访问私有内容
保护protected 类内可以访问 类外不可以访问 儿子可以访问保护内容
struct 和 class都可以创建类
struct 默认权限是公有
class 默认权限是私有
2.构造函数和清理(为了安全)
对象的初始化和清理
构造函数:类名(){}有参数可重载
俩种分类方式:
按参数:有参,无参
按类型:拷贝构造,普通构造
析构函数:~类名(){}无参数所以不可以重载
构造函数调用:
括号法(用这种)
Person p1;默认构造函数
Person p2(10);有参
Person p3(p2);拷贝构造
显示法
Person p1
Person p2 = Person(10)
Person p3 = Person (p2)
隐式转换法
Person p4 =10
Person p5 = p4
3. 深拷贝与浅拷贝
浅拷贝:位拷贝,拷贝构造函数,赋值重载
多个对象共用同一块资源,同一块资源释放多次,崩溃或者内存泄漏。
深拷贝:每个对象共同拥有自己的资源,必须显式提供拷贝构造函数和赋值运算符。
在这里插入图片描述

先释放p2,有指针时使用同一块内存,释放堆区会重复释放
使用深拷贝:
person(const person&p){
m_height = new int(*p.m_height)
*p.m_height 是被拷贝的对象的值
??
???
4.初始化列表
class Person{
Person(int a,int b,int c):m_a(a),m_b(b),m_c{
int ma,m_b,m_c;
}
}

int main(){
Person p(30,20,10)
}
5.类对象做为类的成员
class A{}
class B{
A a;
}
6.构造和析构的顺序
构造:先构造对象成员的构造再构造本类的构造
析构:与之相反
就好像做一台汽车,构造时需要将零件造好才可以再造壳子放在里面,拆卸时先拆壳子
7.静态成员函数
static void func()
{}
有俩种访问方式,用类调用,用对象调用
不属于某一个对象,所有对象共享一个
静态成员函数可以访问静态成员变量,不可以访问非静态成员变量
静态函数也有访问权限,private之后类外就不可以访问了
8.成员变量和成员函数分开存储
类里面有变量时按照变量大小,函数不算大小
没有变量时按照函数占1,给分配
static不算在类中
9.this指针是指针常量,不可修改
this指针本质Person*const this
class Person{
public:
void showPerson()const//常函数,因为对象中this指针默认处处都有,因函数一旦加cosnt,意味着this指针变为
const Person const *this
{this->m_A = 100//报错}
int A_m;
} ;
加mutable后常函数和常对象都可以修改m_A
10.常对象
const Person p;常对象只能调用常函数,不可以调用普通函数,因为常对象不允许修改属性,但是普通函数可以修改属性,相矛盾。

友元

声名一些特殊函数或者特殊的类做访问私有的事

运算符重载

重载的时候最好是和原来意思是一样的,只是运算符对象有变化
1.+号运算符重载
Person PersonaddPersson(Person&p){
Person temp;
temp.m_A = this->m_A +p.m_A
temp.m_B = this ->m_A+p.m_A
return temp;
}
只需要将上面的 PersonaddPerson转变为operate+
即可实现运算符重载
Person operate+ (Person&p)
2.左移运算符重载<<
ostream<<???
3.递增运算符重载++
4.赋值运算符重载=
5.关系运算符><==
6.函数调用运算符重载

继承

好处:减少重复代码
class BasePasage{
public:
void header(){
}
};
class Java:public BasePasage{//继承于BasePasage
}
1.继承的基本方式
公共继承
保护继承
私有继承在这里插入图片描述在父类中私有的成员子类不管是以啥方式继承都继承不到
子类可以用公共方式继承到父类的public和protected且继承后均不改变成员属性
子类可以用protected方式继承到父类的public和protected,且继承后均为protected
子类可以通过private方式继承得到父类的public和protected,且继承后属性均为private
2.继承中的对象模型
父类中所有非静态的属性都会被继承下去,但父类中的私有属性都是被编译器隐藏了,无法访问
3.继承中构造析构的顺序
先构造父类再构造子类
先析构儿子再析构父亲
4.继承中同名的成员处理
Son s;
s.m_A 子类的m_A
s.Base::m_A 父类的m_A
注:子类中如果出现和父类同名的函数,子类的同名成员会隐藏掉所有同名成员函数,也即父类中同名的重载函数都会被覆盖,要想要调用,需要加父类作用域。
5.继承同名静态成员
俩种访问方式,通过类或者对象访问
和普通的成员处理和理解都是一致的
6.多继承
class Base1{
};
class Base2{
};
class Son :public:Base1,public Base2
{};
7.菱形继承
在这里插入图片描述
利用virtual虚继承,解决问题,虚继承后,数据只剩最后继承的一份
底层理解原因:vbptr虚基类指针
在这里插入图片描述虚继承的时候并不是直接的去,再给子类开辟新的空间并把父类的成员复制过来,而是取一个虚基类指针去指向虚继承表,表再根据计算得到具体的指向的是父类的哪一个成员,相当于最后只有父类中的这个成员,因此当菱形继承时,我们需要将中间的那俩个做虚继承,这样最后那个子类继承时就只有一份。

多态

1.静态多态:
函数重载和运算符重载均属于静态多态
2.动态多态:
派生类和虚函数实现运行时多态
静态多态和动态多态的区别:
静态多态 早绑定 编译阶段确定函数地址
动态多态 晚绑定 运行阶段确定函数地址
class Animal{
virtual void speak (){
cout<<"动物在说话“<<endl;
}
};
class cat {
void speak(){
cout<<"猫在说话”<<endl;
}
};
void do_speak(Animal&animal){
animal.speak();
}
int main(){
Cat cat;
do_speak(cat);
}

若父类中的speak函数前没有写virtual关键字,则会在编译时直接和父类Animal绑定,于是会输出“动物在说话”,而一旦加了virtual,则是动态绑定,会输出“猫在说话”。
3.动态多态满足条件
继承关系
子类要重写(返回值类型,参数,名称完全一样)父类的虚函数(例子中的speak函数)
4.动态多态的使用
父类的指针或者引用执行子类对象(例子中的do_speak中的Animal&animal,用的就是父类的引用)
5.多态原理
一般来说子类继承父类会继承父类的所有内容,但是需要注意的是,当使用virtual关键字时,会发生一些变化。
使用virtual时会产生一个虚函数指针,虚函数指针指向虚函数表,表的内容为父类函数入口地址,继承时,子类继承父亲的虚函数指针,但是指针所指向的表是子类自己的虚函数表,表中记录的数据为子类的函数的入口地址,覆盖掉了父类函数,于是当你执行animal.speak()时,实际上是在调用cat.speak(),但是如果没有使用virtual,那么问题就来了,子类会直接将父类的函数和自己的函数都包含,只是作用域不通过,调用的时候,如果是父类Animal&animal做为函数参数,则当传入cat时,执行animal.speak(),会优先执行子类继承过来父类的speak函数,而不是自己的speak函数,可能是优先级的原因,父类的speak函数匹配度更高。
6.纯虚函数和抽象类
virtual 返回值类型 函数名(参数列表) = 0;//纯虚函数
当类中有纯虚函数则为抽象类
抽象类特点:
无法实例化对象
子类必须重写抽象类中的虚函数,否则也是抽象类
7.虚析构和纯虚析构
虚析构
virtual ~Animal(){};
纯虚析构
virtual ~Animal() =0;
8.虚函数表
存储所右虚函数地址的表
析构和构造函数只有类型,参数列表,和函数体,没有函数名

STL背景

建立一套数据结构和算法,产生STL
三兄弟:容器,算法,迭代器
容器和算法通过迭代器无缝连接
六大组件:容器,算法,迭代器,仿函数,适配器,空间配置器
可没有像python那样简单,直接的就像数组一样使用,它需要特殊的算法for_each,以及迭代器i,以及容器list,map,vector才可以实现特定数据的处理
顺序式容器:
vector 像数组即时存取快(类似python numpy) list 像链表好插入删除(类似python list) deque双端队列 (集合了vector和list的优点和缺点)queue队列 priority_queue优先队列,stack栈
关联式容器:
set去重+排序+快速搜索 ,multiset,map(就像python的dict),multimap

vector容器(内容甚至可以是类类型)

1.vector基本语法
第一种:
vector v;//建立了一个vector类型的对像
v.push_back();
vector::iterator itBegin = v.begin();//建立了一个vector作用域下边的iterator类的 itBegin对象
vector::iterator intEnd = v.end();
while(itBegin!=itEnd){
cout<<*itBegin<<endl;
itBegin++;
}
第二种;
for(vector::iterator it = v.begin();it !=v.end;it++){
cout<<*it<<endl;
}
第三种:(暂时不用)
#include
void myPrint(int val){
cout<<val<<endl;
}
for_each(v.begin(),v.end(),myPrint);
2.vector存放自定义数据类型
class Person{
}
vector v;
3.vector 嵌套一个vector(二维数组类似)
vector<vector> v;//很容易理解,就是vector类型的vector里面是int类型的vector
for(vector::iterator it = v.begin(),it!=v.end();it++){
for(vector::iterator itz = (*it).begin();itz != (*it).end();itz++)
{
cout<<*itz<<endl;
}
}

string 容器(类)

find copy delete replace insert
三种构造方法
string s1;

内存泄漏问题

内存泄露:指的是由于疏忽或者错误造成程序未能释放已经不再使用的内存情况。并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
堆内存泄露:堆内存指的是程序运行中根据需要分配通过malloc,realloc new等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果程序的设计错误导致这部分没有被释放,那么此后这块内存将不会再使用,就会产生堆内存泄露。
系统资源泄露:主要指程序使用系统分配的资源比如handle,socket等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。
方法:1.良好的编码习惯,尽量在涉及内存的程序段,检测出内存泄露;对于系统资源使用之前要仔细看其使用方法,防止错误使用或者忘记释放掉系统资源;重载new和delete,将分配的内存以链表的形式自行管理,使用完毕之后从链表中删除,程序结束时可检查该链表,其中记录了内存泄露的文件,所在文件的行数以及泄露的大小哦;尽量避免在堆上分配内存,尽可能使用栈上的内存,由编译器进行分配和回收;引入智能指针;尽量减少手动分配内存,如果需要手动分配数组,尽量使用STL中的分配方式。或者使用STL和boost中的智能指针;凡是使用new和delete的地方,首先注意指针的初始化,然后要注意new和delete的配对,再就是要注意到错误的捕捉,很多时候,内存泄露不是因为new和delete的配对造成的,而是在自己没有考虑到的可能结果中,程序中断而没有delete手动分配的内存。

内存溢出

内存溢出:你要求分配的内存超出了系统所能够给你的,系统不能满足需求,于是产生内存溢出。
常见溢出: 内存未分配成功,却使用了它,方法就是:在使用指针之前检查指针是否为NULL‘
内存分配成功但未初始化就引用它;
内存分配成功并且已经初始化,但操作越过了内存的边界。
使用free 或delete 释放了内存后,没有将指针设置为NULL。导致产生“野指针”。

智能指针

原来有四种智能指针:auto_ptr,unique_ptr,shared_ptr,weak_ptr
其中auto_ptr是C++98提供的解决方案,C++11已经将其摒弃
引用意义:程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理,虽然可以提高程序效率,但是很麻烦,容易造成内存泄露(忘记释放)。使用智能指针方便管理堆内存,它将普通的指针封装成一个栈对象,当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄露。
为什么使用:
作用管理一个指针,在使用普通指针时存在以下这种情况,申请的空间在函数结束时忘记释放,造成内存泄露,使用智能指针可以很大程度上避免这个问题,因为智能指针是一个类,当超出了类的作用域时,类会自动调用析构函数,析构函数会自动释放资源,智能指针的作用就是在函数结束时自动释放内存空间,不需要手动释放内存空间。
shared_ptr:采用引用计数的方法,记录当前内存资源被多少个shared_ptr引用,该引用计数的内存在堆上分配,当新增一个时引用计数加1,当引用过期时计数减一。只有引用计数为0时,shared_ptr才会自动释放引用的内存资源。
引用计数:跟踪引用特定对象的智能指针数,赋值时,计数将加1,而指针过期时,计数将减1,当减为0时才调用delete。
auto_ptr存在潜在的内存崩溃问题,当两个指针指向同一个对象,auto_string采用所有权模式,会存在问题:编译时不报错,运行时候报错。unique_ptr也采用所有权模式,但它在编译时就出错。摒弃auto_ptr:
即auto_ptr存在拷贝语义,拷贝后原对象变得无效,再次访问原对象时会导致程序崩溃,unique_ptr则禁止了拷贝语义,但提供了移动语义,可以使用std::move()进行权限转移。进行move操作后,可以在使用前进行判空操作。upt.get()!=nullptr
避免因为潜在的问题而导致程序崩溃。
reset()可以让unique_ptr提前释放指针
weak_ptr(),它不能决定所指对象的生命周期,引用所指对象时,需要lock()成shared_ptr才能使用。
配合shared_ptr()使用的
在这里插入图片描述

weak_ptr():
是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。使用weak_ptr的成员函数use_count()可以观测资源的引用计数,如果非要使用,可以使用一个成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。还有一个函数expired()的功能类似于use_count() == 0

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_35415875/article/details/108609049

智能推荐

CocosCreator小白入坑之切换场景&角色_cocos怎么配置角色-程序员宅基地

文章浏览阅读9.3k次,点赞4次,收藏15次。记得CocosCreator刚出来的时候就好奇安装了一个。。。因为听说坑很多就一直没有怎么认真去学习,版本变动特别快。我当前版本是1.9的。。。当时是下载的官方稳定版。。。这学期开学回来后,稳定版变1.1了。。。。好了,废话不多说了,直接来干活吧我觉得开发游戏首先是场景的制作,然后是切换,还有一点是玩家操控的角色(PS:三消,塔防等请自行忽略)我们按照开始场景--&gt;游戏场景--&gt..._cocos怎么配置角色

linux描述分区文件fa,鸟哥私房菜 第三章 主机规划与磁盘分区 学习笔记-程序员宅基地

文章浏览阅读68次。在鸟哥的书里面,这句话是经常强调的:在linux系统中,每个设备都被当做是一个文件来对待。目前,我还不能很深入的体会这句话。在这里先记下来,日后慢慢理解。1.下面列出几个常见的设备与其linux当中的文件名,如下:IDE硬盘 /dev/hd[a-d]SCSI/SATA/USB硬盘..._linux描述分区的文件名

Django的ORM操作-程序员宅基地

文章浏览阅读451次。命令,读取已经注册么给app中的migrations目录将配置文件 -> 转换成:生成表,修改表 SQL -> 连接数据库去运行。在app中的models.py中按照规则编写类 ===> 表结构。:请不要再手动去修改数据的表结构 + 时刻保证 ORM和数据表是对应。特点:开发效率高、执行效率低( 程序写的垃圾SQL )。安装MySQL & 启动MySQL服务。orm,关系对象映射,本质翻译的。settings.py,连接数据库。settings.py,注册app。实现:创建表、修改表、删除表。

SVD图像处理(MATLAB)-程序员宅基地

文章浏览阅读440次。使用SVD处理图像模拟演示。

matlab仿真受介质影响的磁场,MATLAB仿真带电粒子在磁场中磁镜现象-程序员宅基地

文章浏览阅读153次。MATLAB仿真带电粒子在磁场中磁镜现象【摘要】借助MATLAB数学工具软件,使用数值计算的方法计算带电粒子磁场中的运动方程,对非均匀磁场的磁镜现象进行仿真,使人们对带电粒子在磁场磁镜现象有个更直观的了解。【关键词】MATLAB;带电粒子;磁场;磁镜现象1.引言对于带电粒子在磁场中的磁镜现象,人们都有了一定的认识,但是却不能对其有比较直观形象的想象。为了比较直观形象的认识带电粒子在磁场中的磁镜现象..._带电粒子在均匀磁场中受洛伦兹力作用matlab

Markdown (CSDN) MD编辑器(二)- 文本样式(更改字体、字体大小、字体颜色、加粗、斜体、高亮、删除线)_markdown语法加粗-程序员宅基地

文章浏览阅读1.4w次,点赞31次,收藏93次。介绍使用 markdown 编辑器时,利用html的 font、mark、strong、em、del、big、small等标签改变文本的颜色、字体、字体大小、加粗字体、斜体、高亮等_markdown语法加粗

随便推点

智能优化算法:麻雀搜索算法-附代码-程序员宅基地

文章浏览阅读10w+次,点赞209次,收藏1.6k次。2020智能优化算法:麻雀搜索算法-附代码文章目录2020智能优化算法:麻雀搜索算法-附代码1.算法原理2.算法结果3.参考文献4.Matlab代码摘要:麻雀搜索算法(Sparrow Search Algorithm, SSA)是于2020年提出的。SSA 主要是受麻雀的觅食行为和反捕食行为的启发而提出的。该算法比较新颖,具有寻优能力强,收敛速度快的优点1.算法原理建立麻雀搜索算法的数学模型,主要规则如下所述:发现者通常拥有较高的能源储备并且在整个种群中负责搜索到具有丰富食物的区域,为所有的加_麻雀搜索算法

成功解决IDEA创建SpringBoot项目时没有web文件夹_idea创建web项目没有web文件夹-程序员宅基地

文章浏览阅读5.1k次,点赞6次,收藏9次。【版权所有,文章允许转载,但须以链接方式注明源地址,否则追究法律责任】原因1.在这块他不是没有文件夹,idea后边把web改成Spring Web了,你就点击那个对勾就可以了2.创建完项目之后发现没有WEB-INFO文件夹点击左上角File–>Projects Structure–>Facets–>Web–>+最后web文件夹就出来了..._idea创建web项目没有web文件夹

达梦数据库实时主备环境的搭建(DM7)-程序员宅基地

文章浏览阅读1.6k次,点赞2次,收藏10次。1 环境说明各主备库的实例名建议采用“组名_守护环境_序号”的方式命名,方便按组区分不同实例,注意总长度不能超过16。本示例中组名为“GRP1”,配置为实时主备,主库命名为“GRP1_DM_01”,备库命名为“GRP1_DM_02”。配置环境说明:主机类型IP地址实例名操作系统主库10.10.35.114(外部服务)1.1.1.10(内部通信)GRP1_DM_0...

java源码分析(五)---HashMap源码_if (var2 >= 1073741824) { this.threshold = integer-程序员宅基地

文章浏览阅读726次。吐槽今天天气好冷啊,真的是冻死了,自己下午出去吃了一顿羊肉泡,美滋滋。回来啃下HashMap的源码。前置条件在看HashMap源码之前我们有两个前置条件:Hash的概念,Hash函数的概念,Hash表的概念Map接口的源码分析当我们看完前置条件,然后再去看下HashMap的源码,解决以下问题。什么时候使用HashMap?简单的介绍下HashMapHashMap的工作原理Ha..._if (var2 >= 1073741824) { this.threshold = integer.max_value; return var1; }

小程序 video 控制器外观调整_可编程逻辑控制器(PLC)软件语言概述-程序员宅基地

文章浏览阅读106次。使用可编程逻辑控制器(PLC)的一个重要部分 ,IEC 61131-3是可编程逻辑控制器国际标准的第三部分。在本标准的这一部分中,列出了PLC的软件体系架构和有效的编程语言。该标准列出了五种不同的语言,其中三种是图形语言,另外两种是基于文本的。语言如下:阶梯图;功能区块图;顺序功能流程图;结构化文字;指令表(第3版标准已弃用)。阶梯图梯形图,通常称为梯形逻辑,是用于PLC编程的最主要语言之一。功能..._在vido中什么是plc组件

ArcGIS 桌面系统_arcgis桌面的几个组成-程序员宅基地

文章浏览阅读816次。ArcGIS桌面系统主要由 ArcMap,ArcCatalog,ArcToolbox三部分组成。利用这三个应用模块,我们可以完成各种GIS任务:从简单的地图显示,制作,到复杂的数据管理,地理分析ArcGIS桌面是集成的,可伸缩性的系统,可以满足不同用户的需要。ArcMapArcMap把传统的空间数据编辑、查询、显示、分析、报表和制图等GIS功能集成到一个简单的可扩展_arcgis桌面的几个组成

推荐文章

热门文章

相关标签