- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在编写的程序中出现了以下模式。我希望它不是太做作,但它设法改变了 Foo
const 方法中的对象 Foo::Questionable() const
, 不使用任何 const_cast 或类似的。基本上,Foo
存储对 FooOwner
的引用反之亦然,在 Questionable()
, Foo
设法通过调用 mutate_foo()
在 const 方法中修改自身在它的主人身上。问题遵循代码。
#include "stdafx.h"
#include <iostream>
using namespace std;
class FooOwner;
class Foo {
FooOwner& owner;
int data;
public:
Foo(FooOwner& owner_, int data_)
: owner(owner_),
data(data_)
{
}
void SetData(int data_)
{
data = data_;
}
int Questionable() const; // defined after FooOwner
};
class FooOwner {
Foo* pFoo;
public:
FooOwner()
: pFoo(NULL)
{}
void own(Foo& foo)
{
pFoo = &foo;
}
void mutate_foo()
{
if (pFoo != NULL)
pFoo->SetData(0);
}
};
int Foo::Questionable() const
{
owner.mutate_foo(); // point of interest
return data;
}
int main()
{
FooOwner foo_owner;
Foo foo(foo_owner, 0); // foo keeps reference to foo_owner
foo_owner.own(foo); // foo_owner keeps pointer to foo
cout << foo.Questionable() << endl; // correct?
return 0;
}
Foo::data
被声明为可变的?或者这是否表明我正在做的事情是致命的错误?我正在尝试实现一种仅在请求时才设置的延迟初始化的“数据”,并且以下代码可以正常编译而没有警告,所以我在 UB 土地上有点紧张。
const
在 Questionable() 上只使直接成员为 const,而不是对象指向或引用的对象。这是否使代码合法?我对
Questionable()
中的事实感到困惑,
this
有类型
const Foo*
,并进一步向下调用堆栈,
FooOwner
合法地有一个非常量指针用来修改
Foo
.这是否意味着
Foo
对象是否可以修改?
class X {
X* nonconst_this; // Only turns in to X* const in a const method!
int data;
public:
X()
: nonconst_this(this),
data(0)
{
}
int GetData() const
{
nonconst_this->data = 5; // legal??
return data;
}
};
最佳答案
考虑以下:
int i = 3;
i
是一个对象,它的类型是
int
.它不是 cv 限定的(不是
const
或
volatile
,或两者。)
const int& j = i;
const int* k = &i;
j
是引用
i
, 和
k
是指向
i
的指针. (从现在开始,我们简单地将“引用”和“指向”结合为“指向”。)
j
和
k
, 指向一个非 cv 限定的对象。这在 §7.1. 5.1/3 中提到:
A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path. [Note: cv-qualifiers are supported by the type system so that they cannot be subverted without casting (5.2.11). ]
j
和
k
是 cv 限定的,即使它们指向一个非 cv 限定的对象。 (所以
j = 5
和
*k = 5
是非法的,即使
i = 5
是合法的。)
const
从那些:
const_cast<int&>(j) = 5;
*const_cast<int*>(k) = 5;
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior. Emphasis mine.
i
不是
const
还有那个
j
和
k
都指向
i
.我们所做的只是告诉类型系统从类型中删除 const 限定符,以便我们可以修改指向的对象,然后修改
i
通过这些变量。
int& j = i; // removed const with const_cast...
int* k = &i; // ..trivially legal code
j = 5;
*k = 5;
i
这是不是:
const int i = 3;
const_cast<int&>(j) = 5;
*const_cast<int*>(k) = 5;
i
是一个 const 限定的对象。我们告诉类型系统删除
const
所以我们可以修改指向的对象,然后修改一个const限定的对象。如上所述,这是未定义的。
int& j = i; // removed const with const_cast...
int* k = &i; // ...but this is not legal!
j = 5;
*k = 5;
const_cast<int&>(j);
*const_cast<int*>(k);
struct foo
{
foo() :
me(this), self(*this), i(3)
{}
void bar() const
{
me->i = 5;
self.i = 5;
}
foo* me;
foo& self;
int i;
};
const
在
bar
对成员(member)做什么?它使对它们的访问通过称为 cv 限定访问路径的东西。 (它通过将
this
的类型从
T* const
更改为
cv T const*
来实现,其中
cv
是函数的 cv 限定符。)
bar
执行过程中的成员类型是什么? ?他们是:
// const-pointer-to-non-const, where the pointer points cannot be changed
foo* const me;
// foo& const is ill-formed, cv-qualifiers do nothing to reference types
foo& self;
// same as const int
int const i;
k
上面是
const int* const
,后者
const
无关紧要。)我们现在考虑:
int main()
{
foo f;
f.bar(); // UB?
}
bar
, 两者
me
和
self
指向非常量
foo
,就像
int i
上面我们有明确定义的行为。如果我们有:
const foo f;
f.bar(); // UB!
const int
一样,因为我们将修改一个 const 限定的对象。
const_cast
Scott Meyers 的技巧,用于在非常量函数中回收一个 const 限定的函数:
struct foo
{
const int& bar() const
{
int* result = /* complicated process to get the resulting int */
return *result;
}
int& bar()
{
// we wouldn't like to copy-paste a complicated process, what can we do?
}
};
int& bar(void)
{
const foo& self = *this; // add const
const int& result = self.bar(); // call const version
return const_cast<int&>(result); // take off const
}
int& bar(void)
{
return const_cast<int&>( // (3) remove const from result
static_cast<const foo&>(*this) // (1) add const to this
.bar() // (2) call const version
);
}
foo
上调用此函数,我们从
int& boo() const
的返回类型中去除 const 限定是完全安全的。 .
const_cast
+ 电话开枪自杀。)
struct foo
{
foo(void) :
i(),
self(*this), me(this),
self_2(*this), me_2(this)
{}
const int& bar() const
{
return i; // always well-formed, always defined
}
int& bar() const
{
// always well-formed, always well-defined
return const_cast<int&>(
static_cast<const foo&>(*this).
bar()
);
}
void baz() const
{
// always ill-formed, i is a const int in baz
i = 5;
// always ill-formed, me is a foo* const in baz
me = 0;
// always ill-formed, me_2 is a const foo* const in baz
me_2 = 0;
// always well-formed, defined if the foo pointed to is non-const
self.i = 5;
me->i = 5;
// always ill-formed, type points to a const (though the object it
// points to may or may not necessarily be const-qualified)
self_2.i = 5;
me_2->i = 5;
// always well-formed, always defined, nothing being modified
// (note: if the result/member was not an int and was a user-defined
// type, if it had its copy-constructor and/or operator= parameter
// as T& instead of const T&, like auto_ptr for example, this would
// be defined if the foo self_2/me_2 points to was non-const
int r = const_cast<foo&>(self_2).i;
r = const_cast<foo* const>(me_2)->i;
// always well-formed, always defined, nothing being modified.
// (same idea behind the non-const bar, only const qualifications
// are being changed, not any objects.)
const_cast<foo&>(self_2);
const_cast<foo* const>(me_2);
// always well-formed, defined if the foo pointed to is non-const
// (note, equivalent to using self and me)
const_cast<foo&>(self_2).i = 5;
const_cast<foo* const>(me_2)->i = 5;
// always well-formed, defined if the foo pointed to is non-const
const_cast<foo&>(*this).i = 5;
const_cast<foo* const>(this)->i = 5;
}
int i;
foo& self;
foo* me;
const foo& self_2;
const foo* me_2;
};
int main()
{
int i = 0;
{
// always well-formed, always defined
int& x = i;
int* y = &i;
const int& z = i;
const int* w = &i;
// always well-formed, always defined
// (note, same as using x and y)
const_cast<int&>(z) = 5;
const_cast<int*>(w) = 5;
}
const int j = 0;
{
// never well-formed, strips cv-qualifications without a cast
int& x = j;
int* y = &j;
// always well-formed, always defined
const int& z = i;
const int* w = &i;
// always well-formed, never defined
// (note, same as using x and y, but those were ill-formed)
const_cast<int&>(z) = 5;
const_cast<int*>(w) = 5;
}
foo x;
x.bar(); // calls non-const, well-formed, always defined
x.bar() = 5; // calls non-const, which calls const, removes const from
// result, and modifies which is defined because the object
// pointed to by the returned reference is non-const,
// because x is non-const.
x.baz(); // well-formed, always defined
const foo y;
y.bar(); // calls const, well-formed, always defined
const_cast<foo&>(y).bar(); // calls non-const, well-formed,
// always defined (nothing being modified)
const_cast<foo&>(y).bar() = 5; // calls non-const, which calls const,
// removes const from result, and
// modifies which is undefined because
// the object pointed to by the returned
// reference is const, because y is const.
y.baz(); // well-formed, always undefined
}
关于c++ - 在没有 const_cast 的情况下修改 *this 的 const 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3484233/
我正在阅读 C++ Primer,我发现了一些非常奇怪且难以理解的东西: Record lookup(Account&); //Record and Account are two unrelate
我的问题是,为什么代码的第一部分不起作用而第二部分有效。非常量指针应该修改之前使用 const_cast 的 const 值,但是对于整数这个技巧不起作用。您能解释一下为什么会这样吗? const i
我已经阅读了很多关于 C++ 中的 const_cast 被认为是错误和危险的讨论,除了向后兼容 C 代码之外,不应将其用于任何其他用途。我大体上同意。 但是最近我遇到了以下用例,这让我感到好奇。 我
C++ Primer 一书的第 6.4 章陈述如下: In § 4.11.3 (p. 163) we noted that const_casts are more useful in the con
我看到这个 post这解释了const_cast<>并说使用指针/引用是有益的。但是,请考虑以下代码: 1- const_cast(xadj) 我得到 invalid const_cast from
我正在阅读有关 c++ 中的 const_cast 运算符 1.我无法理解的第一件奇怪的事情是 const_cast 运算符语法即 -const_cast----(--expression--)---
这个问题在这里已经有了答案: const_cast doesn't work c++? [duplicate] (3 个答案) 关闭 6 年前。 在const_cast之后,main函数中的值没有变
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 我有以下代码: int main(){
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 #include using nam
我想使用 C++ 格式进行此转换,它以 C 方式工作。但是当我尝试使用 C++ 格式时它失败了。 有效! void req_password(const void *data, size_t data
我有一个管理输入的类。要显示和更改键绑定(bind),重要的是在完成后将其提交给管理器之前,为调用者提供它可以拥有和更改的绑定(bind)的映射。但是,这个映射中可以插入/删除什么的具体规则只有管理者
我对 const_cast 的返回类型有点困惑?尖括号内的类型是否 <>是返回类型吗? const int i = 5; int b = const_cast(i); 是const_cast返回 in
我有一个函数 static bool Validate(const char& letter, string& aWord) 我需要调用它 Validate(letter, aWord); // wh
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 考虑以下代码: 我声明了一个新的引用端
我有一个大型库,它实现了一些不可变的数据结构。可以想象,其中几乎所有内容都是 const合格的。有一些选择部分不是 const,例如引用计数器。为了处理嵌入结构中的引用计数器,这些引用计数器只能通过
长话短说是否适用于: mapm; m.insert( make_pair( 1, 40 ) ); for( map::iterator it = m.begin(); it !
据我所知,在类中创建常量函数对于读/写编译器优化很有用。 类中的常量函数意味着类成员在函数执行期间将保持不变。但是,您可以通过 const 强制转换隐式参数来绕过此问题(当然,这是一种非常糟糕的做法)
这个问题在这里已经有了答案: Two different values at the same memory address (7 个答案) 关闭 5 年前。 考虑以下代码: 我声明了一个新的引用端
考虑以下 C++03 程序: #include struct T { mutable int x; T() : x(0) {} }; void bar(int& x) { x
我正在查看我即将开始使用的 API 的一些示例代码。以下模式让我有点困惑: char* str; str = const_cast("Hello World"); printf("%s ", str)
我是一名优秀的程序员,十分优秀!