c ++ const成员函数

时间:2010-07-02 11:43:59

标签: c++ function const member

我正在读一本名为“Effective C ++,Second Edition”的书,以及它关于const成员函数的讨论,以及你如何具有逐位的概念和概念常数。

它说大多数编译器都会使用按位常量,这是因为你无法改变const成员函数内对象的数据成员。

然后有一个成员函数的例子似乎在const测试中没有按位。

它是这样的:

#include "stdafx.h"
#include <string>
#include <iostream.h>

using namespace std;

class mystring
{

public:
    mystring(const char* value);

    operator char *() const { return data; }

private:
    char * data;
};

mystring::mystring(const char * value)
{

    mystring::data = const_cast<char*>(value);
}


int main(int argc, char* argv[])
{
    const mystring s = "Hello";

    char * nasty = s;

    *nasty = 'M';

    printf("s: %c", s);

    return 0;
}

运行此功能时,它会在我的书中说明它应该允许您更改s的值,即使它是const。这是因为char *数据指向与const char*值指向的相同。在这种情况下,*data不是const

但是尝试在MS VC ++ 6.0中运行它,它会在行*nasty = 'M';处抛出访问冲突

有人可以解释发生了什么吗?我想我错过了什么?

对我来说,似乎因为我们有一个const mystring s,我们不应该改变它,但是它在书中所说的内容似乎很尴尬。

4 个答案:

答案 0 :(得分:7)

访问冲突是因为您尝试更改字符串文字。您的代码相当于:

char * p = "Hello";
* p = 'M';

在C和C ++中都是非法的 - 与const成员函数无关。

答案 1 :(得分:2)

您只能获得访问冲突,因为char*指针是字符串文字。更改字符串文字是未定义的行为(在您的情况下为AV),它与const-correctness无关。

答案 2 :(得分:0)

您正在做的是未定义的行为。您正在抛弃常量并尝试修改常量值。如果该例子已经从书中原样复制,那么这本书是错误的。

const_cast<>合法的是将constness从常量指针/引用转移到非const对象:

int i = 5;
int const & ir = i;
const_cast<int&>(ir) = 7; // valid
int const * ip = &i;
*const_cast<int*>(ip) = 9; // valid

const int c = 11;
int const & cr = c;
const_cast<int&>(cr) = 13; // Undefined behavior

你无法从对真正的const对象的引用中抛弃const的原因是编译器可以决定将对象放在只读内存中,在这种情况下,操作可能以不同的方式失败(杀死应用,忽略变化......)

答案 3 :(得分:0)

在您的示例中,您不会更改s,而是尝试更改成员变量s指向的内存。由于您被允许在许多地方放置const,因此您必须小心实际声明const

您的成员函数operator char*() const不允许更改任何成员变量。尝试operator char *() const { data = "something else"; return data; },您的编译器会告诉您不允许修改data。但是,在这种情况下,您只需返回data而无需修改。这是允许的。您甚至可以更改data指向的内存,如operator char *() const { *data = 'M'; return data; }中所示。但是,由于data指向不允许更改的字符串文字,因此在您的上下文中失败。