• C++ (*, &, const, ::) 的一般意义和用法


    0 引言


     《C和指针》中对&操作符,*操作符和const修饰词有一些基本的介绍,这些介绍精确戳中了其本质含义,对于涉及到这些操作符的语法的理解很有帮助。因此写作这篇博文帮助后续的理解。

    reference:

    • 《C和指针》
    • https://stackoverflow.com/questions/3141087/what-is-meant-with-const-at-end-of-function-declaration
    • https://www.cnblogs.com/ghjnwk/p/15555186.html  
    • http://www.mathcs.emory.edu/~cheung/Courses/561/Syllabus/3-C/ref-deref.html  reference and dereference 
    • http://duramecho.com/ComputerInformation/WhyHowCppConst.html
    • https://stackoverflow.com/questions/751681/meaning-of-const-last-in-a-function-declaration-of-a-class

    1 基本含义


     (1)&操作符 (reference operator) and also (address of operator):

    reference operator & operates on a (single) variable name and return the address of  that variable.

    &操作符产生他的操作数的地址。通常用于两个地方:

    • 引用声明: 在引用声明中,& 不应当被理解为取地址,而应当和变量类型int一起被看作是一个整型引用。

      int i = 17;

      int& r = i; ///< 意义: r 是一个初始化为 i 的整型引用

    • 给指针赋值

      int *a;

      int b = 100;

      a = &b;

    (2)*操作符(dereference operator): the dereference operator * operates on an address (an unsigned integer) and return the value stored at that address.

      声明一个指针的含义如下:对 int   *a; 来说,这条语句表示表达式 *a产生的结果类型是int. 知道了*操作符执行的是间接访问操作之后,我们可以推断a肯定是一个指向int的指针。 eg:

    • int *b, c, d;    ///< 声明一个整型指针变量b和两个整型变量c, d
    • int *b, *c, *d; ///< 声明三个整型的指针变量
    • char *message = "hello world";  ///< 这条语句把message声明为一个指向字符的指针,并用字符串常量中第一个字符的地址对该指针进行初始化。  等价于以下:
    • char  *message;  message = "hello world";

      初始化一个指针变量的基本方法

    • int *a = &b;
    • std::cout << "int value at address 136760 = " << *(int* ) 136760 << std::endl;  ///< (type* ) tells compiler how much memory need to be allocated.  

    (3)const修饰词和*指针

    • int const a = 15;  equals  const int a = 15;  目前选择const int a = 15; 作为本人的常用形式
    • const int  *pci;  ///< 含义: pci是一个指针,当解引用(*)pci时,得到一个const int类型的值,表明pci是一个指向const int的指针。
    • const int   *const pci;  ///< 含义: pci是一个指针,当解引用(*)pci时,得到一个const int 类型的值,表明pci是一个指向const int的指针。同时,pci被const修饰,因此pci本身的值和它指向的那个值都不能被修改。
    • #define 和const:  #define指令是另一种创建名字变量的机制。 例子:
      • #define MAX_ELEMENTS 50
      • const int max_element = 50;

          在这种情况下, 使用#define比使用const变量更好。因为只要允许使用字面值变量的地方都可以使用前者,比如声明数组长度。而const变量只能用于允许使用变量的地方。

    2 常量引用的基本规则以及 (const Var&, Var is a class name)


        基本规则1:如果一个普通函数的参数是一个const reference object,那么它将只能够调用被const修饰的类成员函数.  eg:

    #include <iostream>
    
    class Var {
        public:
            Var(const int &size) { d_size = size; }
            int getSize() { return d_size; }
    
        private:
            int d_size;
    };
    
    void noChangeSize(const Var &aa) {
        std::cout << "aa.size = " << aa.getSize() << std::endl;
    }
    
    void TestConstRef()
    {
        Var aa(77);
        std::cout << "aa.size = " << aa.getSize() << std::endl;
        noChangeSize(aa);
    }
    
    int main() {
        TestConstRef();
        return 0;
    }
    

      compiling output:

    test.cpp: In function ‘void noChangeSize(const Var&)’:
    test.cpp:15:45: error: passing ‘const Var’ as ‘this’ argument of ‘int Var::getSize()’ discards qualifiers [-fpermissive]
         std::cout << "aa.size = " << aa.getSize() << std::endl;
    

        下面将另起一章介绍const修饰函数

    3 用const修饰函数


    examples:

    ///< case1: const at the beginning
    const int MyClass::showName(string id){
    ...
    }
    
    ///< case2: const at the end
    int MyClass::showName(string id) const{
    ...
    }
    
    ///< case3: const both at the beginning and at the end
    const int MyClass::showName(string id) const{
    ...
    }
    

      

    (1)const 在函数的名字前面

      在case1中,表示MyClass::showName的返回值是一个const int类型的值。此时有两种调用方式

    • const int id = m.showName("id");   ///< 在这种情况下,被从返回值copy过来的时候,id被初始化为跟返回值一样的类型,不能被修改
    • int id = m.showName("id");             ///< 在这种情况下,id被一个const int 类型的返回值初始化为int类型,此时当然可以被修改

      

    (2)const 在函数的尾巴那里

      在case2中,表示MyClass::showName在操作MyClass的类成员变量是,不应该对其中的变量进行修改。 此处case2的写法相当于传给showName一个const类型的this指针。写作如下:

    • case2 equals  
      int MyClass::showName(const MyClass *this, string id) const{
        ...///< class member of this should not be changed by this function.
      }

      但是也有例外的情形,当class member被mutable修饰的时候,是可以被以const结尾修饰的function修改值的

    #include <iostream>
    
    class Var {
        public:
            Var(const int &size) { d_size = size; }
            int getSize() { return d_size; }
            void setSize(const int& size) const { d_size = size; }
    
        private:
           mutable int d_size;
    };
    
    void noChangeSize(Var* aa) {
        aa->setSize(89); ///< not supported.
        std::cout << "aa.size = " << aa->getSize() << std::endl;
    }
    
    void TestConstRef()
    {
        Var aa(77);
        std::cout << "aa.size = " << aa.getSize() << std::endl;
        noChangeSize(&aa);
    }
    
    int main() {
        TestConstRef();
        return 0;
    }
    

    4 ::


     (1) :: is known as the scope resolution operator.  eg: 

    a. std::cout ,    std::cin  are defined within std , so they have to qualify their names with   std::

    b. foo::foo() {};  class is similar as namespace, 用法类似。

    (2) :: is used to dereference scopes.

    const int x = 5;
    
    namespace foo {
      const int x = 0;
    }
    
    int bar() {
      int x = 1;
      return x;
    }
    
    struct Meh {
      static const int x = 2;
    }
    
    int main() {
      std::cout << x; // => 5
      {
        int x = 4;
        std::cout << x; // => 4
        std::cout << ::x; // => 5, this one looks for x outside the current scope
      }
      std::cout << Meh::x; // => 2, use the definition of x inside the scope of Meh
      std::cout << foo::x; // => 0, use the definition of x inside foo
      std::cout << bar(); // => 1, use the definition of x inside bar (returned by bar)
    }
    
  • 相关阅读:
    Android SDCard操作(文件读写,容量计算)
    weibo4
    weibo5
    android源码结构分析
    后台退出事件
    获取服务器和客户端信息
    vs2008破解升级
    禁止所有蜘蛛
    页面的回发与回传
    显示上一条新闻 下一条新闻
  • 原文地址:https://www.cnblogs.com/ghjnwk/p/15715732.html
Copyright © 2020-2023  润新知