`
dwljd
  • 浏览: 5770 次
  • 性别: Icon_minigender_1
  • 来自: 福建
最近访客 更多访客>>
社区版块
存档分类
最新评论

返回值为引用或指针的成员函数加const要注意

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

成员函数与const

对于不改变类内部成员的成员函数,我们都要在函数后面加上const,对于会改变数据成员的函数则不加const。对成员函数加上const有明确的限制行为:调用该成员函数不会改变内部数据成员。但是,如果const函数的返回值是引用或指针呢?这种情况到底要不要对返回值加上const呢?先来看一段示例:

代码示例与结果

 

#include <iostream>
using namespace std;

struct Node {
    Node* next;
    int value;

    Node() : next(0), value(0){

    }
};


class TestList {
    typedef Node* node_ptr;
    typedef const Node* const_node_ptr;
private:
    node_ptr header;

public:
    TestList() : header(0){

    }

    TestList(node_ptr n) : header(n){

    }

    void print() const {
        node_ptr tmp = header;
        while (tmp != 0){
            cout << tmp->value << (tmp->next == 0 ? "" : ", next: ");
            tmp = tmp->next;
        }
        cout << endl;
    }

    void setHeader(node_ptr n) {
        header = n;
    }

    node_ptr getHeaderPtr() const {
        return header;
    }

    node_ptr& getHeaderRef() const {
        return (node_ptr&)header;
    }
};

int main(int argc, char** argv){
    Node header;
    header.value = 1;

    TestList tl(&header);
//    tl.setHeader(&header);
    cout << "tl ori: " << endl;
    tl.print();

    Node* nptr = tl.getHeaderPtr();
    nptr->value = 2;
    cout << "tl node value can modify by pointer: " << endl;
    tl.print();

    Node refNode;
    refNode.value = 3;
    refNode.next = &header;
    tl.getHeaderRef() = &refNode;
    cout << "tl node can modify by reference: " << endl;
    tl.print();

    cout << "---------------------- const object ----------" << endl;
    const TestList ctl(&header);
    //tl.setHeader(&header);
    cout << "ctl ori: " << endl;
    ctl.print();

    nptr = ctl.getHeaderPtr();
    nptr->value = 5;
    cout << "ctl node value can modify by pointer: " << endl;
    ctl.print();

    Node crefNode;
    crefNode.value = 6;
    crefNode.next = &header;
    ctl.getHeaderRef() = &crefNode;
    cout << "ctl node can modify by reference: " << endl;
    ctl.print();
}

上面示例代码的输出结果:

 

tl ori: 
1
tl node value can modify by pointer: 
2
tl node can modify by reference: 
3, next: 2
---------------------- const object ----------
ctl ori: 
2
ctl node value can modify by pointer: 
5
ctl node can modify by reference: 
6, next: 5

由以上输出可以看到,通过修改const成员函数返回的引用或指针可以修改对象内部的值。这与const函数只能读取内部数据成员(加mutable的数据成员不包括在内)是否相矛盾呢?const函数本身是不会修改数据成员的,但是通过它的返回值可以在外部修改对象内部数据。如果对象是non-const的,这种情况还可以接受;但是如果对象是const的,这种情况就不是所期望的了。

个人建议

 

要防止这种情况发生可以对返回值加const,或者对于在类内部需要把返回值作为左值的则把访问级别限制为public以下(需要再外部修改数据成员的,则提供修改器)。如:

 

    const_node_ptr getHeaderPtr() const {
        return header;
    }

    const node_ptr& getHeaderRef() const {
        return (node_ptr&)header;
    }

 

protected:
    node_ptr getHeaderPtr() const {
        return header;
    }

    node_ptr& getHeaderRef() const {
        return (node_ptr&)header;
    }


当然,对于在成员函数内部通过指针修改数据的就只能自己注意了。


分享到:
评论

相关推荐

    C++中const用法总结.doc

    C++中const用法总结.doc C++中const用法总结.doc 1. const修饰普通变量和指针 2. const修饰函数参数 3. const 修饰函数返回值 4. const修饰类对象/对象...6. const修饰成员函数 7. const常量与define宏定义的区别

    C++常量详解二(常量形参,常量返回值,常量成员函数)

    3.常量成员函数 常量函数里的const是用来修饰*this的,其形式如下: int f() const{```} 然后这里就有意思了 *this的默认类型是type *const this,this指针有一个顶层const,但并没有底层const,由于低层const的...

    C++ 常量成员常量返回值详解

    2.常量成员函数,形式:type funname(type1 arg1,type2 arg2,…) const 1)常量成员函数,不能修改类数据成员,不能调用非常量函数。 2)常量成员函数的作用,可以有效的将类的函数分为可以修改类的函数,和不能修改...

    c-c++及数据结构基础视频教程完整版,最适合自学的c++基础

    05-易犯错误模型-为什么需要成员函数(补充资料)-传智扫地僧 06_课堂答疑类中写成员函数_调用的时才会执行 07_程序设计方法发展历程 08_C语言和C++语言的关系_工作经验分享 09_namespace和iotream 10_实用性加强_...

    零起点学通C++多媒体范例教学代码

    6.9 const成员函数 6.10构造函数 6.11默认构造函数 6.12析构函数 6.13析构对象数组 6.14总结 第7章 循环语句 7.1 循环语句的前身——goto语句 7.2 慎用goto语句 7.3 while语句 7.3.1 带运算符的while语句 7.3.2 以...

    零起点学通C++学习_多媒体范例教学代码

    6.9 const成员函数 6.10构造函数 6.11默认构造函数 6.12析构函数 6.13析构对象数组 6.14总结 第7章 循环语句 7.1 循环语句的前身——goto语句 7.2 慎用goto语句 7.3 while语句 7.3.1 带运算符的while语句...

    新手学习C++入门资料

    除非不可避免,如要调用malloc()函数时要用的void型指针转换成指定类型指针。 四、标准输入输出流 在C语言中,输入输出是使用语句scanf()和printf()来实现的,而C++中是使用类来实现的。 #include iostream.h ...

    Qt源码剖析-智能指针.pdf

    我们可以把类模板看做成⼀个函数 QSharedPointer为函数名, template中类型列表的为函数形参列表,typedef 为返回值。 T最终 的类型确认待你使⽤时由编译器实例化模板时才能推导出),QSharedPointer类模板分别重...

    LuaBind 源码 (Lua增强库)

    1 介绍 LuaBind 是一个帮助你绑定C++和Lua的库....引用或常量引用作为函数的第一个参数.该函数的剩下的参数将在Lua侧可见,而对象指针将被赋值给第一个 参数.如果我们有如下的C++代码: struct A { int ...

    Effective.C++.中文第二版.50条款doc文档.chm

    条款30: 避免这样的成员函数:其返回值是指向成员的非const指针或引用,但成员的访问级比这个函数要低 条款31: 千万不要返回局部对象的引用,也不要返回函数内部用new初始化的指针的引 条款32: 尽可能地推迟变量的...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会主席、北京市人民代表。他是我国计算机普及和高校...8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...

    Effective C++

    条款30:避免这样的成员函数,其返回值是指向成员的非CONST指针或引用 条款31:千万不要返回局部对象的引用,也不要返回函数内部用NEW初始化的指针 条款32:尽可能推迟变量的定义 条款33:明智的使用INLINE 条款34:将...

    经典C/C++面试题目大汇总(全附答案).doc

    (3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    谭浩强教授,我国著名计算机教育专家。1934年生。1958年清华大学毕业。学生时代曾担任清华大学学生会主席、北京市人民代表。他是我国计算机普及和高校...8.3.4 成员函数的存储方式 8.4 对象成员的引用 8.4.1 通过对象名...

    C++高级参考手册 完全自学 内容详细 讲解通俗易懂

    7.4.3 const对象和成员函数 7.4.4 只读存储能力 7.5 可变的(volatile) 7.6 小结 7.7 练习 第8章 内联函数 8.1 预处理器的缺陷 8.2 内联函数 8.2.1 类内部的内联函数 8.2.2 存取函数 8.3 内联函数和编译器 ...

    c++中string类成员函数c_str()的用法

    1.string类成员函数c_str()的原型: const char *c_str()const;//返回一个以null终止的c字符串 2.c_str()函数返回一个指向正规c字符串的指针,内容和string类的本身对象是一样的,通过string类的c_str()函数能够把...

    传智播客扫地僧视频讲义源码

    05-易犯错误模型-为什么需要成员函数(补充资料)-传智扫地僧 06_课堂答疑类中写成员函数_调用的时才会执行 07_程序设计方法发展历程 08_C语言和C++语言的关系_工作经验分享 09_namespace和iotream 10_实用性加强_...

    非常经典的c++ primer视频教程6-10

    相当经典的教程,这次的上传一共5集,5分,相当于每1集要1分下载. 本课程是C++ Primer初级教程,课程内容是学习C++语言基础知识,对应着教材的第1章到第8章。 第1章 快速入门 1.1 编写简单的C++程序 1.2 初窥...

    高级c语言程序编程思想

    8.2 成员函数的重载、覆盖与隐藏 60 8.3 参数的缺省值 63 8.4 运算符重载 64 8.5 函数内联 65 8.6 一些心得体会 68 第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始...

Global site tag (gtag.js) - Google Analytics