`
clskkk2222
  • 浏览: 34921 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论
  • NeuronR: 引用因为用于向函数传递对象和从函数返回对象,该构造函数一般不应 ...
    复制构造函数

数组和指针

    博客分类:
  • C++
阅读更多

数组是由类型名、标识符和维数组成的复合数据类型

数组也是一种存储单一数据类型对象的容器,其中每个对象都没有单独的名字,而是通过它在数组中的位

置对它进行访问。
数组的长度是固定的,数组一经创建,就不允许添加新的元素。

Note:
数组的维数必须用值大于等于1的常量表达式定义
常量表达式只能包含整型字面值常量、枚举常量或者用常量表达式初始化的整型 const 对象。
非 const 变量以及要到运行阶段才知道其值的 const 变量都不能用于定义数组的维数。
(可能会引起不可预料的错误)

数组定义中的类型名可以是内置数据类型或类类型;
除引用之外,数组元素的类型还可以是任意的复合类型;
没有所有元素都是引用的数组.

如果没有显式提供元素初值,则数组元素会像普通变量一样初始化:
在函数体外定义的内置数组,其元素均初始化为 0。
在函数体内定义的内置数组,其元素无初始化。
不管数组在哪里定义,如果其元素为类类型,则自动调用该类的默认构造函数进行初始化;如果该类没有

默认构造函数,则必须为该数组的元素提供显式初始化。
显式初始化的数组不需要指定数组的维数值,编译器会根据列出的元素个数来确定数组的长度:

如果指定了数组维数,那么初始化列表提供的元素个数不能超过维数值。如果维数大于列出的元素初值个

数,则只初始化前面的数组元素;剩下的其他元素,若是内置类型则初始化为0,若是类类型则调用该类

的默认构造函数进行初始化

数组操作

数组下标从零开始,下标是数组元素到开始的偏移量.
数组中元素在内存中连续存放,低编号在低地址,高编号在高地址;

在用下标访问元素时,vector 使用 vector::size_type 作为下标的类型,而数组下标的正确类型则是

size_t

在使用数组时,也必须保证其下标值在正确范围之内,即数组在该下标位置应对应一个元素。

不允许数组直接复制和赋值
个数组不能用另外一个数组初始化,也不能将一个数组赋值给另一个数组

特殊的字符数组

字符数组既可以用一组由花括号括起来、逗号隔开的字符字面值进行初始化,也可以用一个字符串字面值

进行初始化。
字符串字面值包含一个额外的空字符(null)用于结束字符串。当使用字符串字面值来初始化创建的新数

组时,将在新数组中加入空字符

1.输入输出时字符数组名都处理成字符串,对字符变量的地址在输入输出时都会处理成字符串,只有字符

变量地址这样规定;
2.'\0'是字符串唯一合法的结束标志;
3.c++中字符串相比:
 (1)加头文件<string>,格式:变量名==“字符串”;相等为1,不等为0;==只比地址不比内

容;
 (2)加头文件<cstring>, 格式:strcmp(字串1,字串2);结果相等为0,不等结果随意;
4.以下操作需加 头文件<cstring>
 (1)strcpy(变量名,“字符串”):意为把字符串放入字符数组中,是覆盖
 (2)strcat(变量名,“字符串”):意为追加在字符数组后面,追加时需保证字符数组足够大

,以免越界;
 (3)strlen(数组名):计算字符串(不包含'\0')有多长;
5.char型数组输出:cout<< &a[2] << endl;表示从a[2]那个地址开始输出字符串;
6.输入字符串保存在数组中,并不要求输满规定的元素个数,空格或者回车判断输入结束;

字符串字面值的类型就是 const char 类型、以空字符 null 结束的数组
C++ 语言通过(const)char*类型的指针来操纵 C 风格字符串
永远不要忘记字符串结束符 null
调用者必须确保目标字符串具有足够的大小
传递给标准库函数 strcat 和 strcpy 的第一个实参数组必须具有足够大的空间存放新生成的字符串
使用 strn 函数处理C风格字符串

使用标准库函数 strncat 和 strncpy 的诀窍在于可以适当地控制复制字符的个数。特别是在复制和串连

字符串时,一定要时刻记住算上结束符 null.

Note:
对大部分的应用而言,使用标准库类型 string,除了增强安全性外,效率也提高了,因此应该尽量避免

使用 C 风格字符串。

创建动态数组
C++ 语言则使用 new 和 delete 表达式在自由存储区(或堆)中分配存储空间.

new 表达式返回指向新分配数组的第一个元素的指针

动态分配数组时,如果数组元素具有类类型,将使用该类的默认构造函数实现初始化;如果数组元素是内

置类型,则无初始化.

可使用跟在数组长度后面的一对空圆括号,对数组元素做值初始化

对于动态分配的数组,其元素只能初始化为元素类型的默认值,而不能像数组变量一样,用初始化列表为

数组元素提供各不相同的初值。

允许动态分配空数组

C++ 虽然不允许定义长度为 0 的数组变量,但明确指出,调用 new 动态创建长度为 0 的数组是合法的

C++ 语言为指针提供 delete [] 表达式释放指针所指向的数组空间

如果遗漏了空方括号对,这是一个编译器无法发现的错误,将导致程序在运行时出错。

混合使用标准库类 string 和 C 风格字符串

通常,由于 C 风格字符串与字符串字面值具有相同的数据类型,而且都是以空字符 null 结束,因此可

以把 C 风格字符串用在任何可以使用字符串字面值的地方:

可以使用 C 风格字符串对 string 对象进行初始化或赋值。
string 类型的加法操作需要两个操作数,可以使用 C 风格字符串作为其中的一个操作数,也允许将 C

风格字符串用作复合赋值操作的右操作数。

反之则不成立:在要求C风格字符串的地方不可直接使用标准库 string 类型对象。

string 类提供了一个名为 c_str 的成员函数,c_str 函数返回 C 风格字符串,其字面意思是:“返回

C 风格字符串的表示方法”,即返回指向字符数组首地址的指针,该数组存放了与 string 对象相同的内

容,并且以结束符 null 结束。
c_str 返回的指针指向 const char 类型的数组
 
使用数组初始化 vector 对象,必须指出用于初始化式的第一个元素以及数组最后一个元素的下一位置的

地址

多维数组
严格地说,C++ 中没有多维数组,通常所指的多维数组其实就是数组的数组

可以使用由花括号括起来的初始化式列表来初始化多维数组的元素。对于多维数组的每一行,可以再用花

括号指定其元素的初始化式

指针和多维数组
因为多维数组其实就是数组的数组,所以由多维数组转换而成的指针类型应是指向第一个内层数组的指针

用 typedef 简化指向多维数组的指针

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;

int main()
{
    // int& ir[3]; error! declaration of `ir' as array of references 
    
    int ib[] = {0, 1, 2}; // an array of dimension 3
    
    const unsigned array_size = 5;
    // Equivalent to ia = {0, 1, 2, 0, 0}
    // ia[3] and ia[4] default initialized to 0
    int ia[array_size] = {0, 1, 2};
    for(size_t index=0; index!=array_size; ++index)
    {
         cout << ia[index] << " ";
    }
    cout << endl;
    
    // Equivalent to str_arr = {"hi", "bye", "", "", ""}
    // str_arr[2] through str_arr[4] default initialized to the empty string
    string str_arr[array_size] = {"hi", "bye"};
    for(size_t index=0; index!=array_size; ++index)
    {
         cout << str_arr[index] << endl;;
    }
    
    char ca1[] = {'C', '+', '+'};               // no null
    char ca2[] = {'C', '+', '+', '\0'};         // explicit null
    char ca3[] = "C++";                         // null terminator added automatically
    
    //const char ch3[6] = "Daniel";   error: Daniel has 7 elements
    
    cout << "ca1 : " << ca1 << endl; //maybe more than "c++" 
    cout << "ca2 : " << ca2 << endl;
    cout << "ca3 : " << ca3 << endl;
    cout << strlen(ca1) << endl;
    // int ia2[](ia);    error: cannot initialize one array with another
    // int ia3[array_size]; // ok: but elements are uninitialized!
    // ia3 = ia;           //  error:ISO C++ forbids assignment of arrays 
    
    char c1[] = "hello";

    cout << "cout << (int)c1 = " << (int)c1 << endl;
    cout << "cout << &c1[0] : " << &c1[0] << endl;
    cout << "cout << (int)&c1[0] = " << (int)&c1[0] << endl;
    cout << "cout << &c1[2] : " << &c1[2] << endl;
    cout << "cout << (int)&c1[2] = " << (int)&c1[2] << endl;
    
    memset(c1,0,sizeof(c1));
	cout << "after memset(c1,0,sizeof(c1)) ,c1 = " << c1 << endl;
	cout << "strlen(c1) = " << strlen(c1) << endl;
	
    const char *cp1 = "A string example";
    const char *cp2 = "A different string";
    int i = strcmp(cp1, cp2);    // i is positive
    cout << "strcmp(\"" << cp1 << "\",\"" << cp2 << "\") = " << i << endl;
    i = strcmp(cp2, cp1);        // i is negative
    cout << "strcmp(\"" << cp2 << "\",\"" << cp1 << "\") = " << i << endl;
    i = strcmp(cp1, cp1);        // i is zero
    cout << "strcmp(\"" << cp1 << "\",\"" << cp1 << "\") = " << i << endl;

    cout << "strlen(\"" << cp1 << "\") = " << strlen(cp1) << endl;
    cout << "strlen(\"" << cp2 << "\") = " << strlen(cp2) << endl;
    
    // Dangerous: What happens if we miscalculate the size of largeStr?
    char largeStr[16 + 18 + 2];         // will hold cp1 a space and cp2
    strcpy(largeStr, cp1);              // copies cp1 into largeStr
    strcat(largeStr, " ");              // adds a space at end of largeStr
    strcat(largeStr, cp2);              // concatenates cp2 to largeStr
    // prints A string example A different string
    cout << largeStr << endl;

    char largeStr2[16 + 18 + 2]; // to hold cp1 a space and cp2
    strncpy(largeStr2, cp1, 17); // size to copy includes the null
    strncat(largeStr2, " ", 2);  // pedantic, but a good habit
    strncat(largeStr2, cp2, 19); // adds at most 18 characters, plus a null
    cout << largeStr2 << endl;
    
    string *psa = new string[10]; // array of 10 empty strings
    int *pia = new int[10];       // array of 10 uninitialized ints
    for(size_t index=0; index != 10; ++index)
    {
         cout << pia[index] << endl;
    }
    delete [] psa;
    psa = 0;
    delete [] pia;
    pia = 0;

    //const int *pci_bad = new const int[100];  error: uninitialized const array
    const int *pci_ok = new const int[10]();// ok: value-initialized const array
    for(size_t index=0; index != 10; ++index)
    {
         cout << pci_ok[index] << endl;
    }
    delete [] pci_ok;
    pci_ok = 0;
    
    char *cp = new char[0]; // ok: but cp can't be dereferenced
    delete cp;
    cp = 0;
    
    string st = "OneNightInBeijing";
    const char *str = st.c_str(); // ok
    cout << str << endl;
    
    const size_t arr_size = 6;
    int int_arr[arr_size] = {0, 1, 2, 3, 4, 5};
    // ivec has 6 elements: each a copy of the corresponding element in int_arr
    vector<int> ivec(int_arr, int_arr + arr_size);
    for(vector<int>::iterator iter=ivec.begin(); iter!=ivec.end(); ++iter)
    {
         cout << *iter << endl;
    }
    
    int ima[3][4] = {     /*  3 elements, each element is an array of size 4 */
     {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
     {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
     {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
    };
    for(size_t i=0; i!=3; ++i)
    {
      for(size_t j=0; j!=4; ++j)
      {
           cout << ima[i][j] << " ";
      }
      cout << endl;
    }
    cout << endl;
    int imb[][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; //the same as ima
    for(size_t i=0; i!=3; ++i)
    {
      for(size_t j=0; j!=4; ++j)
      {
           cout << imb[i][j] << " ";
      }
      cout << endl;
    }
    cout << endl;
    // explicitly initialize only element 0 in each row
    int imc[3][4] = {{ 0 } , { 4 } , { 8 } };
    for(size_t i=0; i!=3; ++i)
    {
      for(size_t j=0; j!=4; ++j)
      {
           cout << imc[i][j] << " ";
      }
      cout << endl;
    }
    cout << endl;
    int imd[3][4] = {0 , 3, 6 , 9};
    for(size_t i=0; i!=3; ++i)
    {
      for(size_t j=0; j!=4; ++j)
      {
           cout << imd[i][j] << " ";
      }
      cout << endl;
    }
    cout << endl;
     
    int *imp1[4];   // array of pointers to int
    int (*imp2)[4]; // pointer to an array of 4 ints

    // array of size 3, each element is an array of ints of size 4
    int im[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};     
    
    typedef int int_array[4];
    int_array *itp = im;
    cout << itp[2][2] << endl;  //will print 11
    
    for (int_array *p = im; p != im + 3; ++p)
    {
        for (int *q = *p; q != *p + 4; ++q)
        {
          cout << *q << " ";
        }
        cout << endl;
    }
    cout << endl; 
    
    int (*mp)[4] = im; // ip points to an array of 4 ints
    cout << mp[1][0] << endl;   // will print 5
    mp = &im[1];       // ia[2] is an array of 4 ints
    cout << mp[1][0] << endl;   //will print 9
    
    return 0;   
}

 指针是指向某种类型对象的复合数据类型,用于指向对象,保存的是另一个对象的地址

每个指针都有一个与之关联的数据类型,该数据类型决定了指针所指向的对象的类型

C++ 语言使用 * 符号把一个标识符声明为指针

理解指针声明语句时,从右向左阅读

在定义指针变量时,可用空格将符号 * 与其后的标识符分隔开来

如果需要在一个声明语句中定义两个指针,必须在每个变量标识符前再加符号 * 声明:

指针可能的取值
一个有效的指针必然是以下三种状态之一:保存一个特定对象的地址;指向某个对象后面的另一对象;或

者是0值。若指针保存0值,表明它不指向任何对象。未初始化的指针是无效的,直到给该指针赋值后,才

可使用它。

避免使用未初始化的指针,很多运行时错误都源于使用了未初始化的指针。

如果可能的话,除非所指向的对象已经存在,否则不要先定义指针,这样可避免定义一个未初始化的指针

如果必须分开定义指针和其所指向的对象,则将指针初始化为 0。因为编译器可检测出 0 值的指针,程

序可判断该指针并未指向一个对象。

对指针进行初始化或赋值只能使用以下四种类型的值
1. 0 值常量表达式
2. 类型匹配的对象的地址
3. 另一对象末的下一地址
4. 同类型的另一个有效指针
   
初始化或赋值时必须保证类型匹配

C++ 提供了一种特殊的指针类型 void*,它可以保存任何类型对象的地址

void* 表明该指针与一地址值相关,但不清楚存储在此地址上的对象的类型。

void* 指针只支持几种有限的操作:
与另一个指针进行比较;
向函数传递 void* 指针或从函数返回 void* 指针;
给另一个 void* 指针赋值。

不允许使用 void* 指针操纵它所指向的对象。

指针操作
对指针进行解引用可访问它所指的对象,* 操作符(解引用操作符)将获取指针所指的对象

解引用操作符返回指定对象的左值

给指针直接赋值即可修改指针的值——不需要对指针进行解引用。

指针和引用的比较
1. 引用总是指向某个对象,定义引用时没有初始化是错误的
2. 给引用赋值修改的是该引用所关联的对象的值,而并不是使引用与另一个对象关联。引用一经初始化

,就始终指向同一个特定对象

指向指针的指针
指针占用内存空间存放其值,指针的存储地址可存放在指针中

使用指针访问数组元素

在表达式中使用数组名时,该名字会自动转换为指向数组第一个元素的指针

指针的算术操作
通常,在指针上加上(或减去)一个整型数值 n 等效于获得一个新指针,该新指针指向指针原来指向的

元素之后(或之前)的第 n 个元素。

指针的算术操作只有在原指针和计算出来的新指针都指向同一个数组的元素,或指向该数组存储空间的下

一单元时才是合法的。如果指针指向一对象,我们还可以在指针上加1从而获取指向相邻的下一个对象的

指针。

只要两个指针指向同一数组或有一个指向该数组末端的下一单元,C++ 还支持对这两个指针做减法操作

size_t 类型用于指明数组长度,它必须是一个正数;
ptrdiff_t 类型则应保证足以存放同一数组中两个指针之间的差距,它有可能是负数

允许在指针上加减 0,使指针保持不变
如果一指针具有 0 值(空指针),则在该指针上加 0 仍然是合法的,结果得到另一个值为 0 的指针
对两个空指针做减法操作,得到的结果仍是 0

解引用和指针算术操作之间的相互作用 

在指针上加一个整型数值,其结果仍然是指针。允许在这个结果上直接进行解引用操作,而不必先把它赋

给一个新指针
解引用操作符的优先级比加法操作符高

下标和指针
使用下标访问数组时,实际上是使用下标访问指针:

数组本质 <==> 指针 <==> 数组首地址

p[n] <==> *(p+n)
[]适用于所有的指针操作,本质上是指针的操作

数组名是常量,不需要初始化,不能再赋值

不管是什么类型的指针,它的大小都是4 byte(字节)

C++ 允许计算数组或对象的超出末端的地址,对此地址进行解引用操作读到的是垃圾数据

指针是数组的迭代器

指针和 const 限定符:指向 const 对象的指针和 const 指针

如果指针指向 const 对象,则不允许用指针来改变其所指的 const 值。为了保证这个特性,C++ 语言强

制要求指向 const 对象的指针也必须具有 const 特性,不能通过指向const对象的指针修改其所指对象

的值,但是该指针本身并不是 const。在定义时不需要对它进行初始化,如果需要的话,允许给 cptr 重

新赋值,使其指向另一个 const 对象。

不能使用 void* 指针保存 const 对象的地址,而必须使用 const void* 类型的指针保存 const 对象的

地址

允许把非 const 对象的地址赋给指向 const 对象的指针

不能使用指向 const 对象的指针修改基础对象,然而如果该指针指向的是一个非 const 对象,可用其他

方法修改其所指的对象。

不能保证指向 const 的指针所指对象的值一定不可修改,可以把指向 const 的指针理解为“自以为指向

const 的指针”。

在实际的程序中,指向 const 的指针常用作函数的形参。将形参定义为指向 const 的指针,以此确保传

递给函数的实际对象在函数中不因为形参而被修改。

const 指针——本身的值不能修改
与任何 const 量一样,const 指针也必须在定义时初始化。
const指针所指对象的值能否修改完全取决于该对象的类型。

任何企图给 const 指针赋值的行为(即使给 自己赋回同样的值)都会导致编译时的错误。

指向 const 对象的 const 指针
不能修改所指向对象的值,也不允许修改该指针的指向

#include <iostream>
#include <vector>
#include <string>
using namespace std;

int main()
{
    vector<int>   *pvec;      // pvec can point to a vector<int>
    int           *ip1, *ip2; // ip1 and ip2 can point to an int
    string        *ps;   // pstring can point to a string
    double        *dp;        // dp can point to a double
    
    cout << "sizeof(pvec) = " << sizeof(pvec) << endl;    // 4 
    cout << "sizeof(ip1) = " << sizeof(ip1) << endl;      // 4 
    cout << "sizeof(ps) = " << sizeof(ps) << endl; // 4
    cout << "sizeof(dp) = " << sizeof(dp) << endl;        // 4
          
    string* ps1, ps2;  // ps1 is a pointer to string,  ps2 is a string
    string* ps3, *ps4; // both ps1 and ps2 are pointers to string
    
    int ival = 1024;
    int *pi = 0;       // pi initialized to address no object
    int *pi2 = &ival;  // pi2 initialized to address of ival
    int *pi3;          // ok, but dangerous, pi3 is uninitialized
    pi = pi2;          // pi and pi2 address the same object, e.g. ival
    pi2 = 0;           // pi2 now addresses no object

    int zero = 0;
    const int c_ival = 0;
    
    //int *p = ival;   error: p initialized from int value of ival
    //pi = zero;       error: pi assigned int value of zero
    pi = c_ival;    // ok: c_ival is a const with compile-time value of 0
    pi = 0;         // ok: directly initialize to literal constant 0
    pi = NULL;      //ok: equivalent to int *pi = 0;
    
    double dval;
    double* pd = &dval;   // ok: initializer is address of a double
    double* pd2 = pd;     // ok: initializer is a pointer to double
    
    //int *pi2 = pd;    error: types of pi and pd differ
    //pi2 = &dval;      error: attempt to assign address of a double to int *

    int i = 1;
    void *pv = &i;
    cout << (int)pv << endl;
    //cout << *pv << endl;  error! void* is not a pointer-to-object type 
    
    string s("hello world");
    string *sp = &s;          // sp holds the address of s
    cout  << *sp << endl;     // prints hello world
    *sp = "goodbye";          // contents of s now changed
    cout  << *sp << endl;     // prints goodbye
    string s2 = "some value";
    sp = &s2;                 // sp now points to s2
    cout  << *sp << endl;     // prints some value
    
    pi = &ival; // pi points to an int
    int **ppi = π // ppi points to a pointer to int
    pi2 = *ppi; // ppi points to a pointer

    cout << "The value of ival\n"
         << "direct value: ival = " << ival << "\n"
         << "indirect value: *pi = " << *pi << "\n"
         << "doubly indirect value: **ppi = " << **ppi
         << endl;
    
    int ia[] = {0,2,4,6,8};
    int *ip = ia; // ip points to ia[0]
    
    cout << "ia = " << ia << endl;
    cout << "ip = " << ip << endl;
    ip = &ia[4];    // ip points to last element in ia
    cout << "ip = &ia[4], *ip = " << *ip << endl;
    
    ip = ia;
    int *ip3 = ip + 4;  // ok: ip2 points to ia[4], the last element in ia
    cout << "*ip3 = " << *ip3 << endl;
    
    ptrdiff_t n = ip3 - ip; // ok: distance between the pointers
    cout << "ip3 - ip = " << n << endl;
    
    cout << "ip + 0 = " << (ip + 0) << endl;  //ip unchanged
    cout << "ip - 0 = " << (ip - 0) << endl;  //ip unchanged
    
    int *np1 = 0;
    int *np2 = 0;
    cout << "np1 = " << np1 << endl;
    cout << "np2 = " << np2 << endl;
    cout << "np1 + 0 = " << (np1 + 0) << endl;
    cout << "np1 - np2 = " << (np1 - np2) << endl;
    cout << &np1 << endl;
    int *np3 = np1 + 0;
    cout << &(np3) << endl;   //another pointer whose value is 0
    
    int last = *(ia + 4); // ok: initializes last to 8, the value of ia[4]
    cout << "*(ia + 4) = " << last << endl;
    last = *ia + 4;      // assign last to ia[0] + 4 equal to (0+4)
    cout << "*ia + 4 = " << last << endl;
    
    int *p = &ia[2];     // ok: p points to the element indexed by 2
    cout << "p[1] = " << p[1] << endl;  // ok: p[1] equivalent to *(p + 1),
                                        //    p[1] is the same element as ia[3]
    cout << "p[-2] = " << p[-2] << endl;       // ok: p[-2] is the same element as ia[0]
    
    p = ia + 5;
    cout << "ia + 5 = " << *p << endl;
    
    const size_t arr_sz = 5;
    int int_arr[arr_sz] = { 0, 1, 2, 3, 4 };
    // pbegin points to first element, pend points just after the last
    for (int *pbegin = int_arr, *pend = int_arr + arr_sz; pbegin != pend; ++pbegin)
    {
      cout << *pbegin << ' '; // print the current element
    }
    cout << endl;
    
    const double *cptr;  // cptr may point to a double that is const
     
    const double pii = 3.14;
    //double *ptr = &pii;    error: ptr is a plain pointer
    cptr = &pii; // ok: cptr is a pointer to const
    
    const int universe = 42;
    const void *cpv = &universe; // ok: cpv is const
    //void *pv = &universe;      error: universe is const

    double d_val = 3.14; // d_val is a double; its value can be changed
    cptr = &d_val;       // ok: but can't change dval through cptr

    int errNumb = 0;
    int *const curErr = &errNumb; // curErr is a constant pointer
    //curErr = curErr;  error
    
    // pi_ptr is const and points to a const object
    const double *const pi_ptr = &pii;
    
    
    string ss = "snowing";
    typedef string *pstring;
    //const pstring cstr;  error !assignment of read-only variable `cstr' 
    const pstring cstr = &ss;  //ok
    cout << * cstr << endl;

    return 0;   
}

 

分享到:
评论

相关推荐

    数组和指针练习题目(精选)

    数组和指针练习题目(精选) 在编程语言中,数组和指针是非常重要的概念,它们的应用非常广泛,理解基础是非常必要的。本节将通过多种练习题目来加深对数组和指针的理解。 指针基础 指针是一种特殊的变量,它可以...

    数组与指针区别(很全面)

    本文旨在澄清关于数组名是否等同于指针这一常见的误区,并通过具体的代码示例来深入探讨数组和指针之间的关系及其差异。 #### 二、数组与指针的基本概念 1. **数组**: - 数组是一系列相同类型的数据项的集合。 ...

    数组和指针的区别

    虽然数组和指针有相似之处,但在实际编程中需要注意以下几点: - **类型安全**:在使用指针时应确保指针的类型与所指向的数据类型一致,避免类型不匹配导致的问题。 - **内存泄漏**:使用动态内存分配时要注意及时...

    10 数组和指针.pdf

    10 数组和指针.pdf

    数组与指针的艺术.doc

    《数组与指针的艺术》是一篇深度探讨C/C++中数组和指针特性的文章,旨在帮助读者理解和掌握这两种核心概念。文章指出,数组和指针是C/C++语言的灵魂,它们提供了对底层操作的强大支持,是语言效率的保证。然而,由于...

    数组和指针学习资料

    在编程世界中,数组和指针是C/C++等低级语言的核心概念,它们的理解与熟练运用对于程序设计至关重要。本学习资料集包含了对数组和指针的深度解析,旨在帮助学习者彻底掌握这两个概念。 首先,我们来深入探讨数组。...

    C语言数组和指针

    **多维数组指针:** ```c int (*p)[3]; // p是指向含有3个整型元素数组的指针 int (*p)[3] = &a; // 将数组a的地址赋给p ``` **函数指针:** 函数指针是一种特殊的指针类型,它可以存储函数的地址。 ```c int add...

    数组和指针之间的区别与联系

    在C语言中,数组和指针是两个非常重要的概念,它们之间既有明显的区别,也有紧密的联系。数组是一种数据结构,而指针则是一种特殊的数据类型,用于存储内存地址。理解这两者的差异和关联对于深入学习C语言至关重要。...

    数组的指针和指向数组的指针变量

    数组的指针和指向数组的指针变量 数组的指针和指向数组的指针变量是编程语言中一个重要的概念。数组的指针是指向数组在内存中的起始地址,而指向数组的指针变量是指向数组元素的指针变量。 概念: * 数组的指针:...

    数组和指针使用及区别详解

    在编程中,数组和指针是两种非常基础且重要的概念,它们在处理数据时起着核心作用。数组是一组相同类型的元素的集合,通过索引来访问每个元素。指针则是一个变量,它存储的是内存地址,这个地址通常指向一个变量或...

    C++程序设计语言中数组和指针的探讨

    ### C++程序设计语言中数组和指针的探讨 #### 一、引言 在C++编程语言中,数组和指针是两个重要的基础概念,它们不仅被广泛应用于各种编程场景,也是理解更复杂数据结构(如链表、树、图等)的基础。正确理解和运用...

    C语言数组指针(指向数组的指针)_C语言中文网1

    总的来说,理解和熟练运用数组指针是掌握C语言的关键技能之一。它不仅能够帮助我们更有效地操作数组,还能在编写高效的代码时发挥重要作用。在深入学习C语言指针时,还会涉及到二级指针、指针数组、字符串指针、函数...

    C语言程序设计第4章数组和指针

    在C语言中,数组和指针是编程时非常重要的概念,尤其在处理大量数据或实现高效算法时。在第四章“数组和指针”中,我们主要探讨了以下几个知识点: 1. **数组的概念**: 数组是一组相同类型的变量,它们按照下标...

    浅议C语言中数组和指针的互操作

    浅议C语言中数组和指针的互操作浅议C语言中数组和指针的互操作浅议C语言中数组和指针的互操作浅议C语言中数组和指针的互操作

    数组和指针测试数据oj.rar

    在编程领域,数组和指针是C/C++等低级语言中的核心概念,它们在程序设计中扮演着至关重要的角色。数组是一种数据结构,可以存储同类型的数据集合,而指针则是存储内存地址的变量,它能够间接访问和操作数组元素。本...

    C++一维数组和指针的关系总结

    在C++中,一维数组和指针之间存在着密切的关系。本文将从不同角度对这一关系进行详细解释,并通过实例代码帮助理解。 #### 数组名作为地址 首先,我们需要明确的是,在C++中,数组的名字实际上就是该数组第一个...

    数组和指针概念的联系与区分的经典文档.pdf

    在深入探讨之前,首先要明确指针和数组的基本定义。 指针,按照C/C++标准,是一种类型,它可以表示对内存中某个实体的引用。指针类型由"pointer to"和它所指向的类型组成,如"pointer to int"(int*)。指针可以...

Global site tag (gtag.js) - Google Analytics