开发者

C++: Strange behavior of pointer data member in const context

The const qualifier on a method supposed to protect the data member from overwriting by mistake. If you have a data member which is a pointer then only the pointer is defended, the pointed value is not. Is it a flaw in the design of C++ or is there something fundamental thing it serves?

Here is a code which demonstrates the situation. Before reporting irrelevant bugs and style problems, please consider that its sole purpose is to demonstrate the above situation and to be short and straightforward in that.

#include <cstdio>
#include <cstdlib>
#include <cstring>

class Cat
{
public:
        Cat(char const *name)
        : _name(strdup(name))
        { }
        ~Cat(){ free(_name); }
        void SetName(char const *name)
        {
                free(_name);
                _name = strdup(name);
        }
        char const* GetName() const
        {
                _name[0] = 'P';
                return _name;
        }
private:
        char *_name;
};

int main()
{
        Cat c("lost+found");
        c.SetName("Molly");
        printf("%s\n",c.GetName());
        return 0;
}

Compilation went without warnings an开发者_StackOverflowd errors with the following command:

g++ -W -Wall -Wextra -pedantic -Os pmc.cpp -o pmc

The output of the resulting program was Polly.

UPDATE Using pedantic char const * instead of traditional const char *


The fundamental thing served here is simply clarity. The pointer is a member of the class, its pointee is not: It is neither automatically destructed when the class is nor automatically constructed. It might be a wholly different object, so it should not necessarily be const when the class becomes const.

You are desiring something like std::string here, that is, additional semantics for the pointer - for example the guarantee that its contents will not change outside of your class.


The const qualifier on a method supposed to protect the data member from overwriting by mistake. If you have a data member which is a pointer then only the pointer is defended, the pointed value is not.

You have a mistaken perception of the purpose of the const qualifier. It serves three purposes:

  • A const-qualified instance of some class can only call the const-qualified member functions of that class. Calls to member functions that are not const-qualified are forbidden in the case of a const-qualified instance.
  • A const-qualified member function cannot change the direct contents of the instance. Contents that point to data external to the instance are not part of the direct contents of the instance; they simply are not protected by the const qualifier.
  • A huge avenue of optimizations become available to the compiler based on the above.

The const qualifier does not protect you as the author of some class from shooting yourself in your foot (or higher). What it does do is to protect you as the author of some class against someone else doing damage to your class and it allows the compiler to go to town with several optimizations that are not available in a non-const setting.


In the const member function, the type of _name becomes char * const which means it is the pointer which is const, not the data which the pointer points to.

You seem to think that _name becomes const char*. No, the const applies on the pointer, not on the data it points to. So _name has to become char * const.

To minimize this confusion, I prefer the syntax T const over const T even though both are exactly same. Because if T is char*, then T const would become char * const, whereas const T would become const char*. While the former helps understanding, the latter complicates.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜