问题描述
请考虑以下代码。
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;
}
t
是 const
变量和 value()
是一个常量成员函数,它返回 const T&
。 AFAIK不能将 const
类型分配给非const类型。但是 foo * f = t.value();
的编译方式很好。这是怎么回事,如何确保 value()
仅可以分配给 const foo *
?
t
is a const
variable and value()
is a constant member-function which returns const T&
. AFAIK, a const
type is not assignable to a non-const type. But how foo* f = t.value();
compiles well. How this is happening and how can I ensure value()
can be only assigned to const foo*
?
编辑
我发现,这是在使用模板时发生的。以下代码按预期工作。
I found that, this is happening on when templates are used. Following code works as expected.
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;
}
为什么使用模板时出现问题?
Why the problem is happening when templates are used?
推荐答案
因为您有两个间接级别-在您的主函数中,调用 value
返回指向非常量 foo
的const指针的引用。
Because you have two levels of indirection - in your main function, that call to value
returns a reference to a const pointer to a non-const foo
.
这可以安全地复制到非常量中指向非常量 foo
的指针。
This can safely be copied into non-const pointer to a non-const foo
.
如果要实例化 test
和 const foo *
,情况将有所不同。
If you'd instantiated test
with const foo *
, it would be a different story.
const test<const foo*> t;
foo* f = t.value(); // error
const foo* f = t.value(); // fine
return 0;
更新
从注释:
只能读取常量数据。它不能被写入(变异)。但是复制一些数据是一种读取数据的方式,因此可以。例如:
Const data can only be read. It cannot be written ("mutated"). But copying some data is a way of reading it, so it's okay. For example:
const int c = 5;
int n = c;
在这里,我在 c ,然后将数据复制到非常量变量n中。很好,它只是读取数据。
c
中的值尚未修改。
Here, I had some const data in
c
, and I copied the data into a non-const variable n. That's fine, it's just reading the data. The value in c
has not been modified.
现在,假设您的
foo
中包含一些数据:
Now, suppose your
foo
had some data in it:
struct foo { int n; };
如果我有指向其中一个的非常量指针,则可以修改
n
值通过指针。您要求您的 test
模板存储指向非常量 foo
的指针,然后创建一个 test
。因此,仅指针地址是恒定的。没有人可以在 test
内部更改存储在指针中的地址,因此无法使其指向另一个对象。但是,它指向的对象可以修改其内容。
If I have a non-const pointer to one of those, I can modify the
n
value through the pointer. You asked your test
template to store a pointer to a non-const foo
, and then made a const instance of test
. Only the pointer address is constant, therefore. No one can change the address stored in the pointer inside test
, so it cannot be made to point to another object. However, the object it points to can have its contents modified.
更新2:
制作示例的非模板版本时,您犯了一个错误。为正确起见,您需要将
foo *
替换为每个有 T
的地方。
When you made your non-template version of the example, you made a mistake. To get it right, you need to substitute
foo *
into each place where there's a T
.
const T& value() const
请注意,您引用了const
T
在那里。因此,返回值将引用const:a foo *
。这只是指针地址,无法修改。它指向的对象可以修改其内容。
Notice that you have a reference to a const
T
there. So the return value will be a reference to something const: a foo *
. It's only the pointer address that can't be modified. The object it points to can have its contents modified.
在第二个示例中,您摆脱了引用部分,从而改变了含义并使
const
修饰符应用于指针所指向的对象,而不是应用于指针本身。
In your second example, you got rid of the reference part, which changes the meaning and makes the
const
modifier apply to the object that the pointer points to, instead of applying to the pointer itself.
这篇关于const正确性和返回值-C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!