为什么我被告知 “这个方法可以是const”?

huangapple go评论73阅读模式
英文:

Why am I being told "this method could be const"?

问题

在一个类中,可以写如下代码:

class Foo
{
public:
    void DoSomething(int x) const;

private:
    int m_bar;
};

但不允许写如下代码:

void Foo::DoSomething(int x) const
{
    m_bar = x; // 错误
}

我必须移除 const 修饰符。然而,如果我有以下代码:

struct Data
{
    int bar;
};

class Foo
{
public:
    void DoSomething(int x) const;
private:
    Data * m_data;
};

void Foo::DoSomething(int x) const
{
    m_data->bar = x;
}

那么这是允许的,而且如果我移除修饰符,代码验证工具会警告我 "方法可以是 const" 吗?

无论如何,我都不应该能够在 const 方法中修改对象的状态,不管这个状态是如何表示的!

英文:

In a class

class Foo
{
public:
    void DoSomething(int x) const;

private:
    int m_bar;
};

one is not allowed to write

void Foo::DoSomething(int x) const
{
    m_bar = x; // Error
}

I have to remove the const modifier, However, if I have

struct Data
{
    bar;
};

class Foo
{
public:
    void DoSomething(int x) const;
private:
    Data * m_data;
};

void Foo::DoSomething(int x) const
{
    m_data->bar = x;
}

then that's not only fine,but I get warned "method can be const" by code validation tools if I remove the modifier?

I shouldn't be able to modify the state of an object in a const method, irrespective of how that state is represented!

答案1

得分: 7

The const qualifier告诉编译器该函数不会修改对象的任何成员变量。因此,如果您有一个指针成员变量,const 函数将无法更改指针本身。

但是 这仅适用于实际成员变量。指针实际指向的数据不是常量。为此,您需要一个指向常量对象的指针(例如 Data const* m_data;)。

英文:

The const qualifier tells the compiler that the function will not modify any member variables of the object. So if you have a pointer member variable, a const function will not be able to change the pointer itself.

But that only goes for the actual member variable. The data that the pointer is actually pointing to is not constant. For that you need a pointer to a constant object (e.g. Data const* m_data;).

答案2

得分: 2

指针指向某个地方。如果你修改一个指针,你就修改了它指向的位置。

因为指针指向某个地方,所以你可以对它们进行解引用来访问指向的对象。修改对象不会修改指针。

为了说明问题,想象一下,你没有指针,而是有一个数组的索引:

struct Data
{
    int x;
};

Data my_memory[42];

class Foo
{
public:
    void DoSomething(int x) const;
private:
    size_t m_index;  // "指向"my_memory中的一个Data元素
};

void Foo::DoSomething(int x) const
{
    my_memory[m_index].x = x;
}

当然,指针不是数组的索引。尽管作为思维形象,它比你想象的更准确。索引指的是存储在其他地方的实际对象。你可以修改索引,但不会影响对象。你可以使用索引访问对象并修改它,而不会修改索引。这与你的指针所做的事情是一样的。

希望现在很明显 Foo::DoSomething 应该是 const。你正在修改 Data 对象,而它不是 Foo 的一部分。Foo 只包含一个指向对象的指针。DoSomething 不会修改那个指针。

英文:

Pointers point somewhere. If you modify a pointer you modify where it points to.

Because pointers point somewhere you can dereference them to access the pointee. Modifying the pointee does not modify the pointer.


For the sake of illustration, imagine you had no pointer but instead an index into an array:

struct Data
{
    int x;
};

Data my_memory[42];

class Foo
{
public:
    void DoSomething(int x) const;
private:
    size_t m_index;  // "points to" a Data element in my_memory
};

void Foo::DoSomething(int x) const
{
    my_memory[m_index].x = x;
}

Of course pointers are not indices into arrays. Though as mental image it is more accurate than you might expect. The index refers to the actual object which is stored elsewhere. You can modify the index which has no effect on the object. You can use the index to access the object and modify it without modifying the index. Thats just the same as your pointer does.


I hope now it is obvious that Foo::DoSomething should be const. You are modifiying the Data object, which is not part of Foo. Foo only contains a pointer to the object. DoSomething does not modify that pointer.

答案3

得分: 0

对象正在某个地址P处占用一些X内存。
带有const限定符的成员函数无法直接更改此地址上的X内存,这就是函数可以标记为const的原因。

在下面的情况下,我们可以在const对象内更改对象的内存:

struct A {
    public:
    A(): x(5) { x_p =&x;};
    void update_x()  const { *x_p = 3;}
    
     int x;
     int *x_p;
};

编译并运行:

int main()
{   
    A a;
    std::cout << a.x << std::endl;
    a.update_x();
    std::cout << a.x << std::endl;
}

将得到:

3
5
英文:

The object is taking some X memory at some address P.
A member function of with the const qualifier, can't change DIRECTLY the memory X at at this address, this is why a function can be mark as const

In the case below, we CAN change the memory of the object inside a const object

struct A {
    public:
    A(): x(5) { x_p =&x;};
    void update_x()  const { *x_p = 3;}
    
     int x;
     int *x_p;

};

Compile and run :

int main()
{   
    A a;
    std::cout << a.x << std::endl;
    a.update_x();
    std::cout << a.x << std::endl;
}

would get:

3
5

huangapple
  • 本文由 发表于 2023年6月12日 18:35:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76455800.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定