跪求C++中的常量CONST的简单易懂的解释!!!!!!!!!!!!看了10个小时也没看透呀!!!!!!!!!!! 请详细解释一下c++中的new和delete

const \u5728c++\u548cc\u4e2d\u5f97\u5177\u4f53\u533a\u522b\uff01

C\u4e2d\u7684const\uff0c\u529f\u80fd\u6bd4\u8f83\u5355\u4e00\uff0c\u8f83\u5bb9\u6613\u7406\u89e3\uff1a
\u4f5c\u7528\uff1a\u88ab\u4fee\u9970\u7684\u5185\u5bb9\u4e0d\u53ef\u66f4\u6539\u3002
\u4f7f\u7528\u573a\u5408\uff1a \u4fee\u9970\u53d8\u91cf\uff0c\u51fd\u6570\u53c2\u6570\uff0c\u8fd4\u56de\u503c\u7b49\u3002\uff08c++\u4e2d\u5e94\u7528\u573a\u5408\u8981\u4e30\u5bcc\u7684\u591a\uff09
\u7279\u70b9\uff1a \u662f\u8fd0\u884c\u65f6const\uff0c\u56e0\u6b64\u4e0d\u80fd\u53d6\u4ee3#define\u7528\u4e8e\u6210\u4e3a\u6570\u7ec4\u957f\u5ea6\u7b49\u9700\u8981\u7f16\u8bd1\u65f6\u5e38\u91cf\u7684\u60c5\u51b5\u3002\u540c\u65f6\u56e0\u4e3a\u662f\u8fd0\u884c\u65f6const\uff0c\u53ef\u4ee5\u53ea\u5b9a\u4e49\u800c\u4e0d\u521d\u59cb\u5316,\u800c\u5728\u8fd0\u884c\u65f6\u521d\u59cb\u5316\u3002\u5982 const int iConst;\u3002 \u53e6\u5916\uff0c\u5728c\u4e2d\uff0cconst\u53d8\u91cf\u9ed8\u8ba4\u662f\u5916\u90e8\u94fe\u63a5\uff0c\u56e0\u6b64\u5728\u4e0d\u540c\u7684\u7f16\u8bd1\u5355\u5143\u4e2d\u5982\u679c\u6709\u540c\u540dconst\u53d8\u91cf\uff0c\u4f1a\u5f15\u53d1\u547d\u540d\u51b2\u7a81\uff0c\u7f16\u8bd1\u65f6\u62a5\u9519\u3002
c++\u4e2d\u7684const\uff1a\u8ddfc\u4e2d\u6bd4\u8f83\uff0c\u5185\u5bb9\u8981\u4e30\u5bcc\u5f88\u591a\uff0c\u5f53\u7136\uff0c\u4f5c\u7528\u4e5f\u66f4\u5927\u4e86
1\uff1a\u975e\u7c7b\u6210\u5458const
*\u5728c++\u4e2d\uff0cconst\u53d8\u91cf\uff08\u5728\u8fd9\u91cc\u6d89\u53ca\u7684const\u90fd\u4e0d\u662f\u7c7b\u4e2d\u7684const\uff0c\u7c7b\u4e2d\u7684const\u4e13\u95e8\u63d0\u51fa\u6765\u8bb0\u5f55\uff09\u9ed8\u8ba4\u662f\u5185\u90e8\u8fde\u63a5\u7684\uff0c\u56e0\u6b64\u5728\u4e0d\u540c\u7684\u7f16\u8bd1\u5355\u5143\u4e2d\u53ef\u4ee5\u6709\u540c\u540d\u7684const \u53d8\u91cf\u5b9a\u4e49\u3002
*\u662f\u7f16\u8bd1\u65f6\u5e38\u91cf\uff0c\u56e0\u6b64\u53ef\u4ee5\u50cf#define\u4e00\u6837\u4f7f\u7528\uff0c\u800c\u4e14\u56e0\u4e3a\u4e0a\u9762\u4e00\u70b9\uff0c\u53ef\u4ee5\u5728\u5934\u6587\u4ef6\u4e2d\u5b9a\u4e49const\u53d8\u91cf\uff0c\u5305\u542b\u7684\u4e0d\u540c\u7684cpp\u6587\u4ef6\uff08\u7f16\u8bd1\u5355\u5143\uff09\u4e2d\u4f7f\u7528\u800c\u4e0d\u5f15\u8d77\u547d\u540d\u51b2\u7a81\u3002
*\u7f16\u8bd1\u5668\u9ed8\u8ba4\u4e0d\u4e3aconst\u53d8\u91cf\u5206\u914d\u5185\u5b58\uff0c\u9664\u975e\uff1a1. \u4f7f\u7528 extern \u7533\u660e\uff0c 2\uff1a\u7a0b\u5e8f\u4e2d\u6709\u5f15\u7528const \u53d8\u91cf\u7684\u5730\u5740\u3002
* \u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u7c7b\u578b\u8f6c\u6362\uff08\u4e0d\u5b89\u5168\u7684\uff09\uff1a 1: int * = (int *)pConst 2: int * = const_castpConst(c++\u89e3const\u5c5e\u6027cast)
* \u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u503c\u80fd\u4f7f\u7528 const & or const * \u65f6\uff0c\u5c3d\u91cf\u4f7f\u7528const\u5c5e\u6027\uff0c\u589e\u5f3a\u7a0b\u5e8f\u5065\u5168\u6027\u3002
*c++\u4e2d\u4e34\u65f6\u5bf9\u8c61/\u5185\u7f6e\u53d8\u91cf\u9ed8\u8ba4\u5177\u6709const\u5c5e\u6027
2\uff1a\u7c7b\u4e2d\u7684const
*\u7c7b\u4e2d\u7684const\u4e0ec\u8bed\u8a00\u4e2d\u7684const\u4e00\u6837\uff0c\u53ea\u662f\u8fd0\u884c\u65f6\u5e38\u91cf\uff0c\u4e0d\u80fd\u4f5c\u4e3a\u6570\u7ec4\u7ef4\u6570\u4f7f\u7528\uff0c\u5373\u4e0d\u80fd\u53d6\u4ee3#define\u3002\u5728\u7c7b\u4e2d\u4f7f\u7528\u4e0b\u9762\u4e24\u79cd\u65b9\u5f0f\u53d6\u4ee3#define\uff1a 1\uff1astatic const... 2: enum{....}//enum \u4e0d\u5360\u5b58\u50a8\u7a7a\u95f4
*\u7c7b\u4e2d\u7684const \u53d8\u91cf\u5360\u7528\u5b58\u50a8\u7a7a\u95f4
*\u7c7b\u4e2d\u7684const\u6210\u5458\u53d8\u91cf\u9700\u8981\u5728\u6784\u9020\u51fd\u6570\u521d\u59cb\u5316\u5217\u8868\u4e2d\u521d\u59cb\u5316
*const \u5bf9\u8c61\uff1a\u5728\u8be5\u5bf9\u8c61\u751f\u547d\u5468\u671f\u5185\uff0c\u5fc5\u987b\u4fdd\u8bc1\u6ca1\u6709\u4efb\u4f55\u6210\u5458\u53d8\u91cf\u88ab\u6539\u53d8\u3002const\u5bf9\u8c61\u53ea\u80fd\u8c03\u7528const\u6210\u5458\u51fd\u6570\u3002
*const\u6210\u5458\u51fd\u6570\uff1a void fun() const ... \u4e0d\u4ec5\u80fd\u88abconst\u5bf9\u8c61\u8c03\u7528\uff0c\u4e5f\u80fd\u88ab\u975econst\u5bf9\u8c61\u8c03\u7528\uff0c\u56e0\u6b64\uff0c\u5982\u679c\u786e\u8ba4\u4e00\u4e2a\u4efb\u4f55\u6210\u5458\u51fd\u6570\u4e0d\u6539\u53d8\u4efb\u4f55\u6210\u5458\u53d8\u91cf\uff0c\u5e94\u8be5\u4e60\u60ef\u6027\u5c06\u8be5\u51fd\u6570\u5b9a\u4e49\u6210const\u7c7b\u578b\u3002 \u5982\u679cconst\u6210\u5458\u51fd\u6570\u9700\u8981\u6539\u53d8\u6210\u5458\u53d8\u91cf\uff0c\u6709\u4e24\u79cd\u5b9e\u73b0\u65b9\u5f0f\uff1a 1 \uff0cconst_cast this\u5f3a\u5236\u53d6\u6d88this\u6307\u9488\u7684const\u5c5e\u6027\u3002 2\uff1a\u5c06\u88ab\u6539\u53d8\u7684\u6210\u5458\u53d8\u91cf\u5b9a\u4e49\u6210mutable\uff1amutable int i; //\u5e94\u6c38\u8fdc\u53ea\u4f7f\u7528\u7b2c\u4e8c\u79cd\u65b9\u6cd5\uff0c\u8ba9\u4efb\u4f55\u9605\u8bfb\u7a0b\u5e8f\u7684\u4eba\u90fd\u77e5\u9053\u8be5\u53d8\u91cf\u53ef\u80fd\u88abconst\u51fd\u6570\u6539\u53d8\u3002
*\u5982\u679c\u4e00\u4e2a\u5bf9\u8c61\u88ab\u5b9a\u4e49\u6210const\uff0c\u90a3\u4e48\u8be5const\u5bf9\u8c61\u201c\u53ef\u80fd\u201d\u4f1a\u88ab\u653e\u5165\u5230ROM\u5f53\u4e2d\uff0c\u8fd9\u5728\u5d4c\u5165\u5f0f\u5f00\u53d1\u5f53\u4e2d\u6709\u65f6\u975e\u5e38\u91cd\u8981\u3002\u3002\u3002\u3002\uff08\u4e0d\u80fd\u6709\u4efb\u4f55\u81ea\u5b9a\u4e49\u7684constructor \u548cdestructor\u3002\u5b83\u7684\u57fa\u7c7b\u6216\u8005\u6210\u5458\u5bf9\u8c61\u4e0d\u80fd\u6709\u81ea\u5b9a\u4e49\u7684constructor\u548cdestructor\uff0c\u4e0d\u80fd\u6709\u4efb\u4f55mutable\u6210\u5458\u53d8\u91cf\uff09

\u8d44\u6599+\u4e2a\u4eba\u7406\u89e3+\u624b\u6253\uff0c\u7b11\u7eb3O(\u2229_\u2229)O~
\u4e00\u3001new \u548c delete
\u9996\u5148\uff0c\u4f60\u9700\u8981\u77e5\u9053\u7a0b\u5e8f\u5728\u5185\u5b58\u4e2d\u3002\u5b83\u5206\u4e3a\u56db\u90e8\u5206\uff1a
code\uff1a\u4ee3\u7801
data: \u6570\u636e\uff08\u5168\u5c40\u3001\u9759\u6001\u53d8\u91cf\uff09
stack\uff1a\u6808\uff08\u5c40\u90e8\u53d8\u91cf\uff09
heap\uff1a\u5806\uff08\u4f60\u8d1f\u8d23\u7684\u5730\u65b9,\u6bd4\u5982\u7528\u6765\u52a8\u6001\u5185\u5b58\u5206\u914d\uff0c\u5373new\u548cdelete\uff09
\u7a0b\u5e8f\u8fd0\u884c\u65f6\u6240\u9700\u8981\u7684\u6570\u636e\u7a7a\u95f4\uff0c\u901a\u5e38\u662f\u5728\u7a0b\u5e8f\u8bbe\u8ba1\u65f6\u901a\u8fc7\u5b9a\u4e49\u53d8\u91cf\u6216\u6570\u7ec4\u7684\u65b9\u5f0f\uff0c\u7531\u7cfb\u7edf\u9884\u5148\u5206\u914d\u3002\u6bd4\u5982\u5b9a\u4e49\u4e00\u4e2a\u5bf9\u8c61\uff0c\u5728\u7a0b\u5e8f\u8fd0\u884c\u8fc7\u7a0b\uff0c\u5b83\u7684\u7a7a\u95f4\u4e0d\u80fd\u968f\u65f6\u91ca\u653e\u3002
\u3010\u4ea7\u751f\u80cc\u666f\u3011\uff1a\u2460\u5728\u7a0b\u5e8f\u8bbe\u8ba1\u65f6\uff0c\u6709\u4e9b\u6570\u636e\u7a7a\u95f4\u7684\u5927\u5c0f\u548c\u591a\u5c11\u5728\u7f16\u5199\u7a0b\u5e8f\u65f6 \u8fd8\u4e0d\u80fd\u786e\u5b9a\uff0c\u53ea\u6709\u5728\u7a0b\u5e8f\u8fd0\u884c\u65f6\u624d\u80fd\u786e\u5b9a\u3002 \u2461\u6709\u65f6\u5e0c\u671b\u5728\u9700\u8981\u5bf9\u8c61\u65f6\u624d\u5efa\u7acb\uff0c\u4e0d\u9700\u8981\u5c31\u7acb\u523b\u64a4\u9500\u5b83\uff0c\u91ca\u653e\u5176\u5185\u5b58\u4f9b\u522b\u7684\u6570\u636e\u4f7f\u7528\u3002
\u3010\u89e3\u51b3\u3011\uff1a\u4f7f\u7528\u5806(heap)\u5185\u5b58\u53ef\u4ee5\u5b9e\u73b0\u8fd9\u4e00\u529f\u80fd\u3002\u5806\u662f\u4e00\u79cd\u5185\u5b58\u7a7a\u95f4\uff0c\u5b83\u5141\u8bb8\u7a0b\u5e8f\u8fd0\u884c\u65f6 \u6839\u636e\u9700\u8981\u7533\u8bf7\u5927\u5c0f\u7684\u5185\u5b58\u7a7a\u95f4\u3002\u5806\u53c8\u79f0\u52a8\u6001\u5185\u5b58\u5206\u914d\u3002
\u3010\u4f7f\u7528\u65b9\u6cd5\u3011\uff1a
new\u8fd0\u7b97\u7b26:
1\u3001\u4f7f\u7528\u683c\u5f0f:\u6307\u9488\uff1dnew \u6570\u636e\u7c7b\u578b\u540d;
\u6307\u9488\uff1dnew \u6570\u636e\u7c7b\u578b\u540d(\u521d\u59cb\u503c);
\u4f5c\u7528: \u4ece\u5185\u5b58\u7684\u52a8\u6001\u533a\u57df\u7533\u8bf7\u6307\u5b9a\u6570\u636e\u7c7b\u578b\u6240\u9700\u7684\u5b58
\u50a8\u5355\u5143\u3002\u82e5\u5206\u914d\u6210\u529f\uff0c\u8be5\u5b58\u50a8\u5355\u5143\u7684\u9996\u5730\u5740\u8d4b
\u7ed9\u6307\u9488\uff0c\u5426\u5219\uff0c\u6307\u9488\u5f97\u5230\u4e00\u4e2a\u7a7a\u5730\u5740\u3002
\u4f8b\u5982:
(1) double *p;�
p=new double;
(2) double *p;�
p=new double(12.3576); //\u5206\u914d\u540c\u65f6\u521d\u59cb\u5316
2\u3001\u6307\u9488\uff1dnew \u6570\u636e\u7c7b\u578b\u3014\u5143\u7d20\u4e2a\u6570\u3015�
\u7528new\u5728\u5806\u4e2d\u7533\u8bf7\u4e00\u5757\u8fde\u7eed\u7684\u5b58\u50a8\u7a7a\u95f4\uff08\u4e00\u7ef4\u6570\u7ec4\uff09
\u4f8b\uff1a
int size, *ip;
cin>>size;
ip=new int[size]; //\u521b\u5efasize\u4e2a\u5143\u7d20\u7684\u6574\u578b\u6570\u7ec4
char *sp=new char[20]; //\u521b\u5efa20\u4e2a\u5b57\u7b26\u7684\u5b57\u7b26\u6570\u7ec4
delete\u8fd0\u7b97\u7b26\uff1a
\u4f7f\u7528\u683c\u5f0f\uff1a
delete \u6307\u9488\u540d\uff1b //\u91ca\u653e\u6307\u9488\u6240\u6307\u5185\u5b58\u5355\u5143
delete \u3014 \u3015\u6307\u9488\u540d\uff1b //\u91ca\u653e\u6570\u7ec4\u5185\u5b58\u5355\u5143�
\u4f5c\u7528\uff1a\u91ca\u653e\u7528new\u521b\u5efa\u7684\u52a8\u6001\u5b58\u50a8\u5355\u5143 \u3002

\u4f8b\u5982:
int *pi=new int(5);�//\u521b\u5efa
delete pi;� //\u91ca\u653e
pi=new int;� //\u518d\u521b\u5efa
\u3010\u6ce8\u610f\u3011\uff1a
delete\u8fd0\u7b97\u7b26\u5e76\u4e0d\u5220\u9664\u6307\u9488\u3002
\u5bf9\u4e8e\u6307\u5411\u52a8\u6001\u5206\u914d\u5185\u5b58\u5355\u5143\u7684\u6307\u9488\uff0c\u5728\u5176\u6240\u6307\u5411\u7684\u5185\u5b58\u5355\u5143\u6ca1\u6709\u91ca\u653e\u524d\uff0c \u8be5\u6307\u9488\u4e0d\u80fd\u91cd\u65b0\u8d4b\u503c\u3002
\u6bcf\u4e2anew\u8fd0\u7b97\u7b26\u521b\u5efa\u7684\u5185\u5b58\u5355\u5143\uff0c\u53ea\u80fd\u7528delete\u91ca\u653e\u4e00\u6b21\u3002\u800c\u4e14\u4e00\u4e2anew\u5bf9\u5e94\u4e00\u4e2adelete\u662f\u6700\u597d\u7684\u3002

new\u548cdelete\u4f8b\u5b50\u5f88\u4e0d\u7ecf\u610f\u3002\u5b9e\u9645\u7528\u65f6\u53d1\u73b0\u95ee\u9898\u518d\u89e3\u51b3\u5427\u3002

\u4e8c\u3001\u9759\u6001\u6307\u9488 \u52a8\u6001\u6307\u9488
\u597d\u50cf\u6ca1\u6709\u4e13\u95e8\u7684\u5b9a\u4e49\u201c\u9759\u6001\u6307\u9488\u201d\u548c\u201c\u52a8\u6001\u6307\u9488\u201d\u5427\uff01
C++\u4e2d\u5404\u79cd\u6570\u636e\u7c7b\u578b\u90fd\u53ef\u4ee5\u6307\u5b9a\u6307\u9488\u53d8\u91cf\u3002\u6307\u9488\u9664\u4e86\u53ef\u4ee5\u6307\u5411\u4e00\u822c\u53d8\u91cf\u5916\uff0c\u8fd8\u53ef\u4ee5\u6307\u5411\u5176\u4ed6\u4efb\u4f55\u6570\u636e\u7ed3\u6784\u3002\u4e00\u822c\u7684\u6307\u9488\u7684\u7528\u6cd5\u53ca\u8ba1\u7b97\u4f60\u80af\u5b9a\u77e5\u9053\u3002

\u3010\u52a8\u6001\u65b9\u9762\uff1a
\u5728\u7528new\u52a8\u6001\u5efa\u7acb\uff08\u4e0a\u9762\uff09\u4e00\u4e2a\u5bf9\u8c61\u65f6\uff0c\u4f1a\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u65b0\u5bf9\u8c61\u7684\u6307\u9488\u503c\uff0c\u5373\u5206\u914d\u7684\u5185\u5b58\u7a7a\u95f4\u9996\u5730\u5740\u3002\u901a\u8fc7\u8fd9\u4e2a\u6307\u9488\u8c03\u7528\u5bf9\u8c61\u5f88\u65b9\u4fbf\u3002
\u3010\u9759\u6001\u65b9\u9762\uff1a
const \uff1a\u4f7f\u6570\u636e\u5728\u4e00\u5b9a\u8303\u56f4\u5171\u4eab\uff0c\u53c8\u4fdd\u8bc1\u5b83\u4e0d\u88ab\u968f\u610f\u4fee\u6539\u3002\u5373\u5b9a\u4e49\u4e3a\u5e38\u91cf\u3002
\u2460 int * const p = a; //\u5e38\u6307\u9488
const\u4fee\u9970\u6307\u9488\uff0cp\u7684\u6307\u5411\u4e0d\u53ef\u53d8\u3002\u5728\u5b9a\u4e49 \u7684\u65f6\u5019\u6307\u5411\u8c01\uff0c\u5c31\u4e0d\u80fd\u518d\u53d8\u3002
\u2461const int * p = a; //\u6307\u5411\u5e38\u5bf9\u8c61\u7684\u6307\u9488
const \u4fee\u9970\u7c7b\u578bint, p\u6307\u5411\u7684\u6570\u636e\u5185\u5bb9\u4e0d\u53ef\u53d8\uff0c\u5373\u4e0d\u80fd\u901a\u8fc7\u6307\u9488p\u6539\u53d8a\u7684\u503c\uff08\u4f46\u53ef\u4ee5\u901a\u8fc7\u5176\u4ed6\u9014\u5f84\uff09
ps\uff1aconst\u578b\u53d8\u91cf\u53ea\u80fd\u7531 \u8fd9\u79cd\u6307\u9488\u6307\u5411\u5b83\u3002

\u6307\u9488\u592a\u7075\u6d3b\uff0c\u4f7f\u7528\u65f6\u5c0f\u5fc3\u4e3a\u597d\uff0c\u6bd4\u5982\u6307\u9488\u4e0e\u6570\u7ec4\uff0cp++\u548c*p++\u7684\u533a\u522b\u7b49\u7b49\u3002

End\u3002

const就是定义常量啊,比如你写:
const int MY_ERROR=1;
那么你接下去的程序中出现MY_ERROR就跟出现1是相同的.
要注意的是,常量定义之后就不能再改变它的值了,接着上面的例子,比如你又写:
MY_ERROR++;
这是不允许的.
还有一点,常量的定义一般要放到所有的类和函数的外面,所以常量的生命期是最长的,即对整个文件有效.

即使用const的量在之后的程序中都不能进行修改了,const的具体位置代表不同的意思
如 const TYPE NAME (TYPE代表类型,NAME代表这个量的名字)之后的程序中如果尝试修改NAME的值,编译器就会报错

const int& function(void); /*这个函数返回的是一个int的引用,返回的引用不能被修改*/
即不能编写下面的语句:
function = 0; //0只是举例的值而已

又如在类的方法中,下面的函数
void function1(void) const //这个函数不会改变类中任何对象的值

void function2(const int n); //这个函数不能修改n的值

对于语句中有多个const的,可以从右到左去理解
如楼上的:const char* n 可以理解为:到const char 的指针

const 仔细看看。理解应该没问题的,它是定义常量用的,也许你是那个定义指针常量时 不太理解吧,我就只说说这个地方了:
以char型为例,const char* n那么就是定义了一个地址常量,它一旦被付值,那个地址就不能变化了,但是n 指向的内容是可以变化的
char* const m 就是m指向的值不能变了,但是地址却是可以变化的
这需要细细的体会的,

1、什么是const?
常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。(当然,我们可以偷梁换柱进行更新:)

2、为什么引入const?
const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。

3、cons有什么主要的作用?
(1)可以定义const常量,具有不可变性。 例如:
const int Max=100; int Array[Max];
(2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。例如: void f(const int i) { .........} 编译器就会知道i是一个常量,不允许修改; (3)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。 同宏定义一样,可以做到不变则已,一变都变!如(1)中,如果想修改Max的内容,只需要:const int Max=you want;即可!
(4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。 还是上面的例子,如果在函数体内修改了i,编译器就会报错; 例如:
void f(const int i) { i=10;//error! }
(5) 为函数重载提供了一个参考。
class A { ......
void f(int i) {......} //一个函数
void f(int i) const {......} //上一个函数的重载 ......
};
(6) 可以节省空间,避免不必要的内存分配。 例如:
#define PI 3.14159 //常量宏
const doulbe Pi=3.14159; //此时并未将Pi放入ROM中 ......
double i=Pi; //此时为Pi分配内存,以后不再分配!
double I=PI; //编译期间进行宏替换,分配内存
double j=Pi; //没有内存分配
double J=PI; //再进行宏替换,又一次分配内存!
const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。
(7) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

4、如何使用const?
(1)修饰一般常量 一般常量是指简单类型的常量。这种常量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后。 例如:
int const x=2; 或 const int x=2;
(2)修饰常数组 定义或说明一个常数组可采用如下格式:
int const a[5]={1, 2, 3, 4, 5};
const int a[5]={1, 2, 3, 4, 5};
(3)修饰常对象 常对象是指对象常量,定义格式如下:
class A; const A a;
A const a; 定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面。
(4)修饰常指针
const int *A; //const修饰指向的对象,A可变,A指向的对象不可变
int const *A; //const修饰指向的对象,A可变,A指向的对象不可变
int *const A; //const修饰指针A, A不可变,A指向的对象可变
const int *const A;//指针A和A指向的对象都不可变
(5)修饰常引用 使用const修饰符也可以说明引用,被说明的引用为常引用,该引用所引用的对象不能被更新。其定义格式如下:
const double & v;
(6)修饰函数的常参数 const修饰符也可以修饰函数的传递参数,格式如下:
void Fun(const int Var); 告诉编译器Var在函数体中的无法改变,从而防止了使用者的一些无意的或错误的修改。
(7)修饰函数的返回值: const修饰符也可以修饰函数的返回值,是返回值不可被改变,格式如下:
const int Fun1(); const MyClass Fun2();
(8)修饰类的成员函数: const修饰符也可以修饰类的成员函数,格式如下:
class ClassName {
public:
int Fun() const; .....
}; 这样,在调用函数Fun时就不能修改类里面的数据
(9)在另一连接文件中引用const常量
extern const int i;//正确的引用
extern const int j=10;//错误!常量不可以被再次赋值 另外,还要注意,常量必须初始化! 例如: const int i=5;

5、几点值得讨论的地方:
(1)const究竟意味着什么?
说了这么多,你认为const意味着什么?一种修饰符?接口抽象?一种新类型? 也许都是,在Stroustup最初引入这个关键字时,只是为对象放入ROM做出了一种可能,对于const对象,C++既允许对其进行静态初始化,也允许对他进行动态初始化。理想的const对象应该在其构造函数完成之前都是可写的,在析够函数执行开始后也都是可写的,换句话说,const对象具有从构造函数完成到析够函数执行之前的不变性,如果违反了这条规则,结果都是未定义的!虽然我们把const放入ROM中,但这并不能够保证const的任何形式的堕落,我们后面会给出具体的办法。无论const对象被放入ROM中,还是通过存储保护机制加以保护,都只能保证,对于用户而言这个对象没有改变。换句话说,废料收集器(我们以后会详细讨论,这就一笔带过)或数据库系统对一个const的修改怎没有任何问题。
(2)位元const V.S. 抽象const?
对于关键字const的解释有好几种方式,最常见的就是位元const 和 抽象const。下面我们看一个例子: class A { public: ...... A f(const A& a); ...... }; 如果采用抽象const进行解释,那就是f函数不会去改变所引用对象的抽象值,如果采用位元const进行解释,那就成了f函数不会去改变所引用对象的任何位元。 我们可以看到位元解释正是c++对const问题的定义,const成员函数不被允许修改它所在对象的任何一个数据成员。 为什么这样呢?因为使用位元const有2个好处: 最大的好处是可以很容易地检测到违反位元const规定的事件:编译器只用去寻找有没有对数据成员的赋值就可以了。另外,如果我们采用了位元const,那么,对于一些比较简单的const对象,我们就可以把它安全的放入ROM中,对于一些程序而言,这无疑是一个很重要的优化方式。(关于优化处理,我们到时候专门进行讨论) 当然,位元const也有缺点,要不然,抽象const也就没有产生的必要了。 首先,位元const的抽象性比抽象const的级别更低!实际上,大家都知道,一个库接口的抽象性级别越低,使用这个库就越困难。 其次,使用位元const的库接口会暴露库的一些实现细节,而这往往会带来一些负面效应。所以,在库接口和程序实现细节上,我们都应该采用抽象const。 有时,我们可能希望对const做出一些其它的解释,那么,就要注意了,目前,大多数对const的解释都是类型不安全的,这里我们就不举例子了,你可以自己考虑一下,总之,我们尽量避免对const的重新解释。
(3)放在类内部的常量有什么限制?
看看下面这个例子:
class A {
private:
const int c3 = 7; // ???
static int c4 = 7; // ???
static const float c5 = 7; // ??? ......
};
你认为上面的3句对吗?呵呵,都不对!使用这种类内部的初始化语法的时候,常量必须是被一个常量表达式初始化的整型或枚举类型,而且必须是static和const形式。这显然是一个很严重的限制! 那么,我们的标准委员会为什么做这样的规定呢?一般来说,类在一个头文件中被声明,而头文件被包含到许多互相调用的单元去。但是,为了避免复杂的编译器规则,C++要求每一个对象只有一个单独的定义。如果C++允许在类内部定义一个和对象一样占据内存的实体的话,这种规则就被破坏了。
(4)如何初始化类内部的常量?
一种方法就是static 和 const 并用,在内部初始化,如上面的例子; 另一个很常见的方法就是初始化列表:
class A {
public:
A(int i=0):test(i) {}
private:
const int i;
}; 还有一种方式就是在外部初始化,例如:
class A {
public:
A() {}
private:
static const int i;//注意必须是静态的!
};
const int A::i=3;
(5)常量与数组的组合有什么特殊吗? 我们给出下面的代码:
const int size[3]={10,20,50};
int array[size[2]];
有什么问题吗?对了,编译通不过!为什么呢?
Const可以用于集合,但编译器不能把一个集合存放在它的符号表里,所以必须分配内存。在这种情况下,const意味着“不能改变的一块存储”。然而,其值在编译时不能被使用,因为编译器在编译时不需要知道存储的内容。自然,作为数组的大小就不行了:) 你再看看下面的例子:
class A {
public:
A(int i=0):test[2]({1,2}) {}//你认为行吗?
private:
const int test[2];
};
vc6下编译通不过,为什么呢? 关于这个问题,前些时间,njboy问我是怎么回事?我反问他:“你认为呢?”他想了想,给出了一下解释,大家可以看看:我们知道编译器堆初始化列表的操作是在构造函数之内,显式调用可用代码之前,初始化的次序依据数据声明的次序。初始化时机应该没有什么问题,那么就只有是编译器对数组做了什么手脚!其实做什么手脚,我也不知道,我只好对他进行猜测:编译器搜索到test发现是一个非静态的数组,于是,为他分配内存空间,这里需要注意了,它应该是一下分配完,并非先分配test[0],然后利用初始化列表初始化,再分配test[1],这就导致数组的初始化实际上是赋值!然而,常量不允许赋值,所以无法通过。 呵呵,看了这一段冠冕堂皇的话,真让我笑死了!njboy别怪我揭你短呀:)我对此的解释是这样的:C++标准有一个规定,不允许无序对象在类内部初始化,数组显然是一个无序的,所以这样的初始化是错误的!对于他,只能在类的外部进行初始化,如果想让它通过,只需要声明为静态的,然后初始化。 这里我们看到,常量与数组的组合没有什么特殊!一切都是数组惹的祸!
(6)this指针是不是const类型的?
this指针是一个很重要的概念,那该如何理解她呢?也许这个话题太大了,那我们缩小一些:this指针是个什么类型的?这要看具体情况:如果在非const成员函数中,this指针只是一个类类型的;如果在const成员函数中,this指针是一个const类类型的;如果在volatile成员函数中,this指针就是一个volatile类类型的。
(7)const到底是不是一个重载的参考对象?
先看一下下面的例子:
class A {
......
void f(int i) {......}//一个函数
void f(int i) const {......}//上一个函数的重载
......
}; 上面是重载是没有问题的了,那么下面的呢?
class A {
......
void f(int i) {......}//一个函数
void f(const int i) {......}//?????
......
}; 这个是错误的,编译通不过。那么是不是说明内部参数的const不予重载呢?再看下面的例子:
class A {
......
void f(int& ) {......}//一个函数
void f(const int& ) {......}//?????
......
}; 这个程序是正确的,看来上面的结论是错误的。为什么会这样呢?这要涉及到接口的透明度问题。按值传递时,对用户而言,这是透明的,用户不知道函数对形参做了什么手脚,在这种情况下进行重载是没有意义的,所以规定不能重载!当指针或引用被引入时,用户就会对函数的操作有了一定的了解,不再是透明的了,这时重载是有意义的,所以规定可以重载。
(8)什么情况下为const分配内存?
以下是我想到的可能情况,当然,有的编译器进行了优化,可能不分配内存。
A、作为非静态的类成员时;
B、用于集合时;
C、被取地址时;
D、在main函数体内部通过函数来获得值时;
E、const的 class或struct有用户定义的构造函数、析构函数或基类时;。
F、当const的长度比计算机字长还长时;
G、参数中的const;
H、使用了extern时。 不知道还有没有其他情况,欢迎高手指点:)
(9)临时变量到底是不是常量?
很多情况下,编译器必须建立临时对象。像其他任何对象一样,它们需要存储空间而且必须被构造和删除。区别是我们从来看不到编译器负责决定它们的去留以及它们存在的细节。对于C++标准草案而言:临时对象自动地成为常量。因为我们通常接触不到临时对象,不能使用与之相关的信息,所以告诉临时对象做一些改变有可能会出错。当然,这与编译器有关,例如:vc6、vc7都对此作了扩展,所以,用临时对象做左值,编译器并没有报错。
(10)与static搭配会不会有问题? 假设有一个类:
class A {
public:
......
static void f() const { ......}
......
}; 我们发现编译器会报错,因为在这种情况下static不能够与const共存! 为什么呢?因为static没有this指针,但是const修饰this指针,所以...
(11)如何修改常量?
有时候我们却不得不对类内的数据进行修改,但是我们的接口却被声明了const,那该怎么处理呢?我对这个问题的看法如下:
1)标准用法:
mutable class A {
public:
A(int i=0):test(i) { }
void SetValue(int i)const { test=i; }
private: mutable int test;//这里处理!
};
2)强制转换:
const_cast class A {
public:
A(int i=0):test(i) { }
void SetValue(int i)const {
const_cast (test)=i;
}//这里处理!
private:
int test;
};
3)灵活的指针:
int* class A {
public:
A(int i=0):test(i) { }
void SetValue(int i)const { *test=i; }
private:
int* test; //这里处理!
};
4)未定义的处理
class A {
public:
A(int i=0):test(i) { }
void SetValue(int i)const {
int *p=(int*)&test; *p=i;
}//这里处理!
private:
int test;
}; 注意,这里虽然说可以这样修改,但结果是未定义的,避免使用!
5)内部处理:this指针
class A {
public:
A(int i=0):test(i) { }
void SetValue(int i)const {
((A*)this)->test=i;
}//这里处理!
private:
int test;
};
6)最另类的处理:空间布局
class A {
public:
A(int i=0):test(i),c('a') { }
private:
char c;
const int test;
};
int main()
{
A a(3);
A* pa=&a;
char* p=(char*)pa;
int* pi=(int*)(p+4);//利用边缘调整
*pi=5;//此处改变了test的值!
return 0;
}
虽然我给出了6中方法,但是我只是想说明如何更改,但出了第一种用法之外,另外5种用法,我们并不提倡,不要因为我这么写了,你就这么用,否则,我真是要误人子弟了:)
(12)最后我们来讨论一下常量对象的动态创建。 既然编译器可以动态初始化常量,就自然可以动态创建,例如:
const int* pi=new const int(10); 这里要注意2点:
1)const对象必须被初始化!所以(10)是不能够少的。
2)new返回的指针必须是const类型的。 那么我们可不可以动态创建一个数组呢? 答案是否定的,因为new内置类型的数组,不能被初始化。 这里我们忽视了数组是类类型的,同样对于类内部数组初始化我们也做出了这样的忽视,因为这涉及到数组的问题,我们以后再讨论。

  • c 涓const鏄粈涔堟剰鎬
    绛旓細鍦C璇█涓紝const鏄竴涓慨楗扮锛岃〃绀哄父閲忕殑鎰忔濄傚湪瀹氫箟涓涓彉閲忔椂鍔犱笂const鍏抽敭瀛楋紝鍙互浣胯鍙橀噺鎴愪负涓嶅彲淇敼鐨勫父閲銆傚父閲忎竴鏃﹁祴鍊煎悗灏变笉鑳借淇敼锛屼篃灏辨槸璇达紝const淇グ鐨勫彉閲忓兼槸鍙鐨勩傝繖鍙互鏈夋晥閬垮厤鍦ㄧ▼搴忎腑涓嶅皬蹇冧慨鏀硅鍙橀噺鍊艰屽紩鍙戠殑閿欒锛屾彁楂樼▼搴忕殑鍋ュ.鎬сconst鐨鐢ㄦ硶鍜屾敞鎰忎簨椤 const鍙互搴旂敤...
  • const鍦╟璇█涓殑鐢ㄦ硶
    绛旓細璇ヨ瑷涓昏鐢ㄩ旀槸瀹氫箟甯搁噺锛屽嵆涓嶅彲淇敼鐨勫彉閲忋const鍙互鐢ㄦ潵瀹氫箟甯搁噺锛屽嵆鍦ㄧ▼搴忚繍琛屾湡闂村叾鍊间笉鑳芥敼鍙樼殑鍙橀噺銆備緥濡傦紝const int MAX_VALUE =100锛 瀹氫箟浜嗕竴涓悕涓篗AX_VALUE鐨勫父閲锛屽叾鍊间负100锛屼笖杩欎釜鍊煎湪绋嬪簭杩愯鏈熼棿涓嶈兘琚敼鍙樸俢onst涔熷彲浠ヤ笌鎸囬拡涓璧蜂娇鐢紝浠ラ槻姝㈡寚閽堟寚鍚戠殑鍊艰淇敼銆傚湪鍑芥暟鍙傛暟涓娇鐢...
  • c璇█涓const 鏄粈涔堟剰鎬,鎬庝箞鐢,浠涔堟椂鍊欑敤?
    绛旓細const 琛ㄧず甯搁噺锛岀浉褰撲簬瀹忓畾涔夛紝鍙兘璇诲彇锛屼笉鑳戒慨鏀广傚父鍙橀噺锛歝onst 鏁版嵁绫诲瀷 绗﹀彿甯稿彉閲 = 鏁板 濡傦細const float PI=3.14;鎸囬拡甯搁噺锛氭暟鎹被鍨 *const 鎸囬拡鍙橀噺=鍙橀噺鍚 濡傦細char *const p="abc";const淇グ鐨勬槸鎸囬拡鍙橀噺锛岃屼笉鏄寚閽堢殑鍊硷紝鎵浠ユ寚閽堟寚鍚戠殑鍊兼槸鍙互淇敼鐨勩傚父鎸囬拡锛歝onst 鏁版嵁绫诲瀷 *...
  • const鍦╟璇█涓殑鐢ㄦ硶
    绛旓細1.const鏄C璇█涓殑鍏抽敭瀛楋紝涓昏浣滅敤鏄檺瀹氫竴涓彉閲忎笉鍏佽琚敼鍙橈紝浜х敓闈欐佷綔鐢ㄣ備娇鐢╟onst鍦ㄤ竴瀹氱▼搴︿笂鍙互鎻愰珮绋嬪簭鐨勫畨鍏ㄦу拰鍙潬鎬с傞櫎浜嗗父瑙勭殑瀹氫箟甯搁噺澶栵紝const杩樺彲浠ヤ慨楗板眬閮ㄥ彉閲忋佸叏灞鍙橀噺銆佸彉閲忔寚閽堜互鍙婁綔涓哄嚱鏁板弬鏁 2.鍦–璇█涓紝const鏈甯歌鐨勭敤娉曟槸浣滀负鏁扮粍鐨勮竟鐣屽拰switch鍒嗘儏鍐垫爣鍙凤紝鍚屾椂涔熷彲浠ュ畾...
  • c璇█涓const 鏄粈涔堟剰鎬?
    绛旓細锛1锛夊彲浠ュ畾涔const甯搁噺锛屽叿鏈変笉鍙彉鎬с備緥濡傦細const int Max=100; Max++浼氫骇鐢熼敊璇;锛2锛変究浜庤繘琛岀被鍨嬫鏌ワ紝浣跨紪璇戝櫒瀵瑰鐞嗗唴瀹规湁鏇村浜嗚В锛屾秷闄や簡涓浜涢殣鎮c備緥濡傦細 void f(const int i) { ...} 缂栬瘧鍣ㄥ氨浼氱煡閬搃鏄竴涓父閲忥紝涓嶅厑璁镐慨鏀癸紱锛3锛夊彲浠ラ伩鍏嶆剰涔夋ā绯婄殑鏁板瓧鍑虹幇锛屽悓鏍峰彲浠ュ緢鏂逛究鍦拌繘琛...
  • c璇█涓殑const鐨鍖哄埆?
    绛旓細涓銆佸尯鍒涓嬶細1銆乮nt瀹氫箟鐨勯噺鏄彉閲忥紝瀹冪殑鍊煎彲浠ユ洿鏀癸紱鑰宑onst int 瀹氫箟鐨勬槸涓涓甯搁噺锛屽畠鐨勫间笉鍙互鏇存敼銆2銆乮nt鍦ㄥ畾涔夌殑鏃跺欙紝涓嶉渶瑕佸垵濮嬪寲锛岃宑onst int 鍦ㄥ畾涔夌殑鏃跺欏繀椤诲垵濮嬪寲锛涗簩銆const鐨浣滅敤锛氭妸瀵硅薄杞崲鎴愪竴涓父閲
  • const鍦╟++涓殑浣滅敤
    绛旓細const鐢ㄤ簬瀹氫箟甯搁噺銆俢onst鐢ㄤ簬闄愬畾鎸囬拡鎴栭檺瀹氭寚鍚戠殑鍐呭銆俢onst鍦ㄧ被瀹氫箟涓殑浣跨敤銆俢onst绫诲瀷甯搁噺鍚=甯搁噺;锛1锛夊父閲忎竴缁忓畾涔夊氨涓嶈兘淇敼锛屼緥濡傦細constinti=5;//瀹氫箟甯搁噺i锛宨=10;//閿欒锛屼慨鏀瑰父閲忥紝i++;//閿欒锛屼慨鏀瑰父閲忋傦紙2锛const甯搁噺蹇呴』鍦ㄥ畾涔夋椂鍒濆鍖栵紝渚嬪锛歝onstintn;//閿欒锛屽父閲弉鏈鍒濆鍖...
  • 璺眰C++涓殑甯搁噺CONST鐨绠鍗曟槗鎳傜殑瑙i噴!!!鐪嬩簡10涓皬鏃朵篃娌$湅閫忓憖...
    绛旓細const灏辨槸瀹氫箟甯搁噺鍟,姣斿浣犲啓:const int MY_ERROR=1;閭d箞浣犳帴涓嬪幓鐨勭▼搴忎腑鍑虹幇MY_ERROR灏辫窡鍑虹幇1鏄浉鍚岀殑.瑕佹敞鎰忕殑鏄,甯搁噺瀹氫箟涔嬪悗灏变笉鑳藉啀鏀瑰彉瀹冪殑鍊间簡,鎺ョ潃涓婇潰鐨勪緥瀛,姣斿浣犲張鍐:MY_ERROR++;杩欐槸涓嶅厑璁哥殑.杩樻湁涓鐐,甯搁噺鐨瀹氫箟涓鑸鏀惧埌鎵鏈夌殑绫诲拰鍑芥暟鐨勫闈,鎵浠ュ父閲忕殑鐢熷懡鏈熸槸鏈闀跨殑,鍗冲...
  • c璇█涓const淇グ鐨勫埌搴曟槸甯搁噺杩樻槸鍙橀噺?
    绛旓細C璇█涓璫onst淇グ鐨勯噺鏄父鍙橀噺锛屽畠涓庢櫘閫氬彉閲忕殑缂栬瘧鏂瑰紡涓鏍凤紝鍞竴鐨勫尯鍒槸甯稿彉閲忓畾涔夊悗涓嶈兘鍋氬乏鍊笺侰++涓璫onst淇グ鐨勬墠鏄甯搁噺銆1銆 const淇グ鐨勫彉閲忔槸甯搁噺杩樻槸鍙橀噺 瀵逛簬杩欎釜闂锛屽緢澶氬悓瀛﹁涓篶onst淇グ鐨勫彉閲忔槸涓嶈兘鏀瑰彉锛岀粨鏋滃氨璇涓鸿鍙橀噺鍙樻垚浜嗗父閲忋傞偅涔堝浜巆onst淇グ鐨勫彉閲忚濡備綍鐞嗚В閭o紵涓嬮潰鎴戜滑鏉...
  • C++涓const浠涔堟剰鎬?
    绛旓細鍦ㄦ爣鍑咰++涓紝杩欐牱瀹氫箟鐨勬槸涓涓甯搁噺锛岀敤鏉ヤ慨楗板唴缃被鍨嬪彉閲忥紝鑷畾涔夊璞★紝鎴愬憳鍑芥暟锛岃繑鍥炲硷紝鍑芥暟鍙傛暟銆const浣跨敤锛堢被鍨嬶級:1銆佺敤浜庢寚閽堢殑涓ょ鎯呭喌:const鏄竴涓乏缁撳悎鐨勭被鍨嬩慨楗扮.int const*A;//A鍙彉,*A涓嶅彲鍙 int*const A;//A涓嶅彲鍙,*A鍙彉 2銆侀檺瀹氬嚱鏁扮殑浼犻掑煎弬鏁:void function(const int ...
  • 扩展阅读:c++中<< ... c++简单程序实例 ... c++ static ... c++struct ... c++ mysql ... c++软件 ... 延时c# ... c++编程 ... c++onnxruntime推理 ...

    本站交流只代表网友个人观点,与本站立场无关
    欢迎反馈与建议,请联系电邮
    2024© 车视网