const正确性和返回值 - C++

Nav*_*K N 0 c++ constants const-correctness

请考虑以下代码.

struct foo
{
};

template<typename T>
class test
{
public:   

    test() {} 

    const T& value() const
    {
        return f;
    }

private:
    T f;
};


int main()
{
    const test<foo*> t;
    foo* f = t.value();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

t是一个const变量,value()是一个返回的常量成员函数const T&.AFAIK,const类型不能分配给非const类型.但如何foo* f = t.value();编译好.如何发生这种情况以及如何确保value()只能分配给const foo*

编辑

我发现,这是在使用模板时发生的.以下代码按预期工作.

class test
{
public:   

    test() {} 

    const foo* value() const { return f; }

private:
    foo* f;
};


int main()
{
    const test t;
    foo* f = t.value(); // error here
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么在使用模板时会出现问题?

Dan*_*ker 6

因为你有两个间接级别 - 在你的main函数中,该调用value返回对一个指向非const的const指针的引用foo.

这可以安全地复制到非const指针到非const foo.

如果你实例testconst foo *,这将是一个不同的故事.

const test<const foo*> t;
foo* f = t.value(); // error
const foo* f = t.value(); // fine
return 0;
Run Code Online (Sandbox Code Playgroud)

更新

来自评论:

value()返回const T&只能分配给另一个const类型.但在这种情况下,编译器可以安全地进行转换.

只能读取Const数据.它不能写("变异").但是复制一些数据是一种阅读方式,所以没关系.例如:

const int c = 5;
int n = c;
Run Code Online (Sandbox Code Playgroud)

在这里,我有一些const数据c,我将数据复制到非const变量n中.没关系,它只是读取数据.值in c尚未修改.

现在,假设你foo有一些数据:

struct foo { int n; };
Run Code Online (Sandbox Code Playgroud)

如果我有一个指向其中一个的非const指针,我可以n通过指针修改该值.您要求您的test模板存储指向非const的指针foo,然后创建一个const实例test.因此,只有指针地址是常量.没有人可以改变存储在指针里面的地址test,因此不能指向另一个对象.但是,它指向的对象可以修改其内容.

更新2:

当您创建示例的非模板版本时,您犯了一个错误.要做到正确,你需要替换foo *到每个有的地方T.

const T& value() const
Run Code Online (Sandbox Code Playgroud)

请注意,您在T那里引用了const .所以返回值将是对const的引用:a foo *.它只是指针地址无法修改.它指向的对象可以修改其内容.

在第二个示例中,您删除了引用部分,它更改了含义并使const修饰符应用于指针指向的对象,而不是应用于指针本身.