修改常量对象

时间:2013-07-24 12:06:05

标签: c++ c++11 const constants undefined-behavior

我正在通过面试问题向初级C ++开发人员的位置看。问题是(引用):

  

以下代码是否正确

struct Foo
{
    int i;
    void foo ( void ) const
    {
        Foo* pointer = const_cast<Foo*>(this);
        pointer->i = 0;
    }
};

我会回答:

  

代码本身根据C ++ 03和c ++ 11标准有效,并且将成功编译。   但它可能会在分配指针 - &gt; i期间调用未定义的行为   = 0; 如果调用 foo()的类的实例声明为 const

我的意思是以下代码将成功编译并导致未定义的行为。

struct Foo
{
    int i;
    Foo ( void )
    {

    }
    void foo ( void ) const
    {
        Foo* pointer = const_cast<Foo*>(this);
        pointer->i = 0;
    }
};

int main ( void )
{
    Foo foo1;
    foo1.foo();   // Ok

    const Foo foo2;
    foo2.foo();   // UB

    return 0;
}

我的回答是正确的还是我遗失了什么?谢谢。

3 个答案:

答案 0 :(得分:5)

我首先会问他们对“正确”的模糊定义是什么意思。您需要了解该计划的规范及其预期行为

正如你所说,如果他们只是在询问它是否编译,那么答案就是'是'。但是,如果他们认为做得安全是正确的,那么您可以讨论您在问题中陈述的事实。

通过回答这种方式,面试的人可以看到你是如何分析你被问到的,而不是直接回答,这在我看来是一件好事。

答案 1 :(得分:1)

这段代码可能在法律上是正确的,但我想,问题的目的是确定你是否理解const本身的概念。因为,在语义层面上,你有一个带有隐式const对象指针的函数,然后它会被修改,这几乎肯定是一个bug。

有些情况下,可能需要这样做(因为修改是一些返回值的缓存,或类似的操作,不会改变对象的语义值),您可以使用mutable关键字有问题的变量。

答案 2 :(得分:0)

作弊编译器将承担后果。

struct Foo
{
    int i;

    Foo(int a):i(a){}

    void foo ( void ) const
    {
        Foo* pointer = const_cast<Foo*>(this);
        pointer->i = 0;
    }

    bool operator<(const Foo& rhs) const{
        return i<rhs.i;
    }
};

#include <map>

int main ( void )
{
    std::map<Foo,int> kk;

    for(int i=0;i<10;++i){
        kk.insert(std::make_pair(Foo(i),i));
    }

    std::map<Foo,int>::iterator ite = kk.find(Foo(4));
    const Foo& foo4 = ite->first;
    foo4.foo();

    ite = kk.find(Foo(4));
    const Foo& tmp = ite->first; // crack

    return 0;
}

程序将破解“const Foo&amp; amp = ite-&gt; first;”