几年没写程式了,有些比较基础的地方有点模糊.写个笔记.

变量的声明定义:

1、在头文件的类外面定义。这样定义的变量可认为是对外公开的全局变量定义,因为一般别人引用你的头文件,是可以直接看到的,所以是公开的,在类外面就是全局的,只要你包含这个头文件,就会分配空间。
2、在头文件类里面定义。这是公开非全局。生命周期和类对象生命周期一致。
3、cpp函数外定义。这是非公开全局。非公开的意思是,一般来说两个子系统合作,是不会提供cpp文件的,只会提供头文件和lib库。
4、函数内定义,就是局部变量。

除了第4种,其他三种在别的地方都可以引用,只不过第3种要加external。

在哪里定义变量是有讲究的,如果全部定义全局变量,会有两个弊端:
1、浪费内存空间。因为只要你包含了它,不管你有没有用到,都会分配空间。
2、不安全,破坏封装性。全局变量很容易被读取。这也就是为什么会有private这个东西。

关于break,return,continue:

break是退出for while等循环一次退单层,return是退出包含循环的函数退出整个函数,continue是退出本次循环进行下次循环

因为break一次只能跳出一层循环,所以如果想从多层嵌套中迅速跳出有以下方法:
1、goto语句
while(condition1)
{
  while(condition2)
  {
    while(condition3)
      if(some disaster)
        goto quit;
  }
}
quit: 
   ;
2、设置一个状态标志:

bool flag = true;
for (int i = 0; i < datagridview.Rows.Count&&flag ; i++) 
                { 
                    for (int j = 0; j < datagridview.Columns.Count&&flag ; j++) 
                    { 
                        if (datagridview.Columns[j].Visible == true && !System.Convert.IsDBNull(datagridview[j, i].Value)) 
                        { 
                            string cellcontain = System.Convert.ToString(datagridview[j, i].Value).ToUpper(); 
                            int index = cellcontain.IndexOf(condition.ToUpper(), 0); 
                            if (index >= 0) 
                            { 
                                datagridview.CurrentCell = datagridview[j, i]; 
                                iscontinue = false; 
                               flag  = false;
                            } 
                        } 
                        else 
                            continue; 
                    } 
                }

3.作一个方法
用return就可以了。

关于static:

          用static修饰的成员是描述整个非静态类的,不管实例化多少个对象,在内存中只存在一份数据,所有
的对象都可以使用它。如果是静态类的成员,那么不用实例化,直接使用就好比如Math类.

关于new:

一/当非指针对象(或者说构造函数出了问题)用NEW新建对象会报错"尝试引用已删除的函数"

Union 是C/C++语言中的一种结构类型,用于定义可共享内存的数据变量的一种方式,初次使用Union联合体时可能会遇到以下问题:

 错误 C2280 Union : 尝试引用已删除的函数 

 警告 C4624 “Grade”: 已将析构函数隐式定义为“已删除”

不多说,上代码:

// TemplateExe1.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <iostream>
#include "atlstr.h"
using namespace std;
union Grade {
    int number;
    CString mark;
    bool pass;
    
}uGrade;
int main()
{
    uGrade.number = 90;
    printf("%d",uGrade.number);
    getchar();
    
    return 0;
}
此错误的原因:CString 是一个类,有自己的构造函数,析构函数。

解决方案:CString 换成基本的数据类型:char 等

我们分析一下:

Union的一大特征在于,一个Union类中的所有数据共享同一段内存。
如果union类的成员包含自己的构造函数,析构函数,那么同一Union类的成员在初始化时,就有可能会执行不同的构造函数。
这是无法预料的。
所以,我们在定义Union类时要尽量避免成员变量是对象(含有自己的构造函数)。

二/摘抄一段:FAQ: C++中定义类的对象:用new和不用new有何区别? - 狂涛爱蕞 - 博客园:

#include <iostream>

using namespace std;

class A

{

private:

int n;

public:

    A(int m):n(m)//初始化列表,必须要使用列表初始化的几种情况 - Dobben - 博客园.主体意思就是初始化列表在构造函数之前动作.

    {

    }

    ~A(){}

};

int main()

{

     A a(1);  //栈中分配

    A b = A(1);  //栈中分配

    A* c = new A(1);  //堆中分配

  delete c;

    return 0;

}

第一种和第二种没什么区别,一个隐式调用,一个显式调用,两者都是在进程虚拟地址空间中的栈中分配内存,而第三种使用了new,在堆中分配了内存,而栈中内存的分配和释放是由系统管理,而堆中内存的分配和释放必须由程序员手动释放,所以这就产生一个问题是把对象放在栈中还是放在堆中的问题,这个问题又和堆和栈本身的区别有关:

这里面有几个问题:

1.堆和栈最大可分配的内存的大小

2.堆和栈的内存管理方式

3.堆和栈的分配效率

首先针对第一个问题,一般来说对于一个进程栈的大小远远小于堆的大小,在linux中,你可以使用ulimit -s (单位kb)来查看一个进程栈的最大可分配大小,一般来说不超过8M,有的甚至不超过2M,不过这个可以设置,而对于堆你会发现,针对一个进程堆的最大可分配的大小在G的数量级上,不同系统可能不一样,比如32位系统最大不超过2G,而64为系统最大不超过4G,所以当你需要一个分配的大小的内存时,请用new,即用堆。

其次针对第二个问题,栈是系统数据结构,对于进程/线程是唯一的,它的分配与释放由操作系统来维护,不需要开发者来管理。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时,这些存储单元会被自动释放。栈内存分配运算内置于处理器的指令集中,效率很高,不同的操作系统对栈都有一定的限制。 堆上的内存分配,亦称动态内存分配。程序在运行的期间用malloc申请的内存,这部分内存由程序员自己负责管理,其生存期由开发者决定:在何时分配,分配多少,并在何时用free来释放该内存。这是唯一可以由开发者参与管理的内存。使用的好坏直接决定系统的性能和稳定。

由上可知,但我们需要的内存很少,你又能确定你到底需要多少内存时,请用栈。而当你需要在运行时才知道你到底需要多少内存时,请用堆。

最后针对第三个问题,栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率 比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在 堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会 分 到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

由上可知,能用栈则用栈。

举个简单的例子:
class Point
{
 private:
   int x;
   int y;
 public:
   void Set(int a,int b)
   { x=a; y=b; }
   void Print()
   { cout<<"("<<x<<","<<y<<")"<<endl; }
};

void main()
{
  Point p1;
  Point *p2=new Point();
  p1.Set(1,2);
  p2->Set(4,5);
  
  p1.Print();
  p2->Print();
  delete p2;
}
对象p1,p2的定义方式有何本质不同?用哪种方式比较好?
p1有系统创建并释放,你不要担心会出现内存泄露,但是生命期只有在本区域的大括号内,出了大括号就没用了。P2是指针,要自己释放,用不好很危险,用好了功能强大,因为他可以赋值给全局的变量,一下子从局部变量变成全局变量,还能把对象作为函数返回值。

关于全局变量:

#include <QCoreApplication>
#include "abc.h"
#include <QDebug>
QString message;//写在.cpp的函数外,或者.h文件的class外就是全局变量了.但是最好就用static全局变量,更安全稳妥.
int main(int argc, char *argv[])
{   
 QCoreApplication a(argc, argv);     
 qDebug()<<("hello world!");   
 return a.exec();
}
 

关于extern:

        extern 声明不是定义,也不分配存储空间。事实上,它只是说明变量定义在程序的其他地方。程序中变量可以声明多次,但只能定义一次。只有当声明也是定义时,声明才可以有初始化式,因为只有定义才分配存储空间。初始化式必须要有存储空间来进行初始化。如果声明有初始化式,那么它可被当作是定义,即使声明标记为 extern:
extern double pi = 3.1416; // definition
虽然使用了 extern ,但是这条语句还是定义了 pi,分配并初始化了存储空间。只有当 extern 声明位于函数外部时,才可以含有初始化式,在函数体内部写extern double pi = 3.1416;是会报错的.

由于头文件包括在多个源文件里。而且变量的定义仅仅能出现一次,所以在头文件里, 仅仅能够声明不能够出现定义.

实验如下:

  

///

keil c的extern跟qt的又不一样.

头文件声明:

extern extern uint8_t  abc[56];

在此头文件的c文件或者其他包含此头文件的地方定义:

 uint8_t  abc[56]={0x00};

此处如果定义时和qt一样不带变量类型会报错未定义类型,应该说规范更严谨了.

 

关于变量的定义位置:

在VC中,变量定义在头文件中为public时,其对象可见.而在CPP中声明定义不能加public private修饰符.但其默认为private只在本cpp中可见.

在C++中,变量的定义应在.cpp源文件中,头文件中只可声明变量。

如果变量 int a ;定义在.cpp中,但在.h文件中用到了a;则在.h文件中声明extern int a;

如果一定要在.h文件中定义,则可以这样定义 inline int  a;

原因:.h文件是不参与编译的,所以,如果在.h文件中定义了变量,那么在链接过程就会出错。

文件的标准命名法:  C++ 语言文件: 头文件.h 源文件.cpp

 

更多推荐

编程的基础知识点