一、const指针的几个区别
(1)const int* p 与int const *p 修饰值,不能改变指针所指的值;
- const 修饰的是整个*p,所以*p是个常量,是不能被赋值的。
- p前并没有用const修饰,所以p是指针变量,能被赋值重新指向另一个内存地址。
(2)int* const p 修饰指针,不能改变指针的地址;
- p因为有了const修饰,所以p值是不可修改的
- 整个*p的前面没有const的修饰,也就是说,*p是变量,所以可以通过*p来修改它所指内存的值。
(3)const int *const p
- p是常量,所以不能把test2的地址赋给p;同时*p也是常量,所以*p的内容不可更改。
二、条款2:尽可能使用const
1、C++中变量常量的声明和定义
1)变量的定义默认为extern,要想使常量(const变量)能够在其他文件中访问,必须在定义时显示指定它为extern。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//mytest.cpp #include "stdafx.h" //声明定义变量,默认为extern int objectInDefFile = 10; //声明定义常量,要使常量可以在其他文件中访问,必须显示指定为extern extern const int constInDefFile = 100; //使用extern int x,y;只是声明了x,y这两个变量,它告诉编译器其后的变量已经在别的文件中说明,不再为它们分配内存。 extern int x,y; void Func2(){ y=x*10; cout<<"y:"<<y<<endl; } void PrintHello(){ cout<<"Hello"<<endl; Func2(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include "stdafx.h" #include "mytest.h" #include "iostream" using namespace std; //必须声明才能使用其他文件定义的变量 extern int objectInDefFile; //必须声明才能使用其他文件定义的常量 extern const int constInDefFile; int x,y; extern void PrintHello(); //声明PrintHello() void Fun1(){ x=123; cout<<"x:"<<x<<endl; } int _tmain(int argc, _TCHAR* argv[]){ Fun1();//x=123 PrintHello();//调用mytest.cpp中的PrintHello()函数并调用Func2()函数 y=1230 //cout << "objectInDefFile: " << constInDefFile << std::endl; //cout << "objectInDefFile: " << objectInDefFile << std::endl; //const int *ptr; //GamePlayer gameplayer; ////ptr=&gameplayer::NumTurns; //int a=sizeof(GamePlayer); return 0; } |
2、iterator与const_iterator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include <vector> int _tmain(int argc, _TCHAR* argv[]){ std::vector<int> vec; for(int i=0;i<10;i++) vec.push_back(i); const std::vector<int>::iterator iter=vec.begin(); *iter=10; //++iter; std::vector<int>::const_iterator cIter=vec.begin(); //*cIter=10; ++cIter; return 0; } |
调用方式:获取迭代器指针
1 2 3 4 |
TmdsIterator beginIter = result.cbegin(); TmdsIterator endIter = result.cend(); TmdsIterator FirstUSCCIter=FindEightUSCC( beginIter, endIter); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
class EXPORT_DECLSPEC TmdsStream : public Serializable{ private: DmaCapture _capture; public: typedef TmdsIterator const_iterator; TmdsStream(); TmdsStream(DmaCapture&& capture); TmdsStream(const TmdsStream& other); TmdsStream(TmdsStream&& other); const_iterator cbegin() const;//注意是const_iterator const_iterator cend() const; virtual void Save(std::string path) const; static TmdsStream Open(std::string path); friend class TmdsIterator; friend class TmdsDecodedIterator; friend class TmdsDescramblingIterator; }; TmdsStream::const_iterator TmdsStream::cbegin() const { return TmdsIterator(*this);// } TmdsIterator(*this)调用下列函数 */TmdsIterator::TmdsIterator(const TmdsStream& stream) : _stream(&stream), DmaIterator(/*stream._capture.cbegin()*/ TimestampIterator<1028,4>::MakeBeginIterator(stream._capture.cbegin(), stream._capture.cend()), TimestampIterator<1028,4>::MakeBeginIterator(stream._capture.cbegin(), stream._capture.cend()), TimestampIterator<1028,4>::MakeEndIterator(stream._capture.cbegin(), stream._capture.cend())) {}*/ |
3、常量成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
// functionconst.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <cstring> #include <string.h> #include "iostream" using namespace std; class TextBlock{ std::string text; public: TextBlock(){} ~TextBlock(){} TextBlock(std::string mystring){ text=mystring; } //operator[] for const对象,确认该成员函数可作用于const对象 const char& operator[](std::size_t position)const{ return text[position]; } //调用 const operator[] //将*this从原始类型TextBlock&转型为const TextBlock& //将从const operator[]的返回值const char& 移除为const char& operator[](std::size_t position){ return const_cast<char&>( static_cast<const TextBlock&>(*this)[position] ); } ////将其operator[]声明为const 成员函数,而该函数返回一个reference指向对象内部值 //char& operator[](std::size_t position)const{ // return pText[position]; //} void print(const TextBlock&ctb){ std::cout<<ctb[0]; } }; //class CTextBlock{ // char *pText; // std::size_t textLength;//最近一次计算的文本区块长度 // bool lengthIsValid; //目前的长度是否有效 //public: // CTextBlock(){} // ~CTextBlock(){} // // CTextBlock(char* myptext){ // pText=myptext; // } // // std::size_t length()const; // // // //将其operator[]声明为const 成员函数,而该函数返回一个reference指向对象内部值 // char& operator[](std::size_t position)const{ // return pText[position]; // } //}; class CTextBlock{ char *pText; //mutable 表示这些成员变量总是会被更改,即使是在const成员函数内 mutable std::size_t textLength;//最近一次计算的文本区块长度 mutable bool lengthIsValid; //目前的长度是否有效 public: CTextBlock(){} ~CTextBlock(){} CTextBlock(char* myptext){ pText=myptext; } std::size_t length()const; //将其operator[]声明为const 成员函数,而该函数返回一个reference指向对象内部值 char& operator[](std::size_t position)const{ return pText[position]; } }; std::size_t CTextBlock::length() const{ if (!lengthIsValid){ //Error 1 error C3490: 'textLength' cannot be modified //because it is being accessed through a const object textLength=std::strlen(pText); lengthIsValid=true; } return textLength; } int _tmain(int argc, _TCHAR* argv[]){ TextBlock tb("hello"); std::cout<<tb[0]<<endl;; tb[0]='x'; const TextBlock ctb("World"); std::cout<<ctb[0]<<endl; //ctb[0]='W'; const CTextBlock cctb("Hello");//声明一个常量对象 char *pc=&cctb[0];//调用const operator[]取得一个指针,指向cctb的数据 char *t="J"; pc=t; *pc='J'; //Unhandled exception at 0x00143543 in functionconst.exe: 0xC0000005: Access violation writing location 0x00149838. //ctb[0]='x'; system("pause"); return 0; } |