这是一个语言律师问题,而不是一个好的练习题.
以下代码是有效还是未定义的行为?const对象最终调用非const函数,但它实际上并不修改对象的状态.
struct Bob
{
Bob() : a(0) {}
int& GetA()
{
return a;
}
const int& GetA() const
{
return const_cast<Bob&>(*this).GetA();
}
int a;
};
int main()
{
const Bob b;
int a = b.GetA();
}
Run Code Online (Sandbox Code Playgroud) 我有两个版本的相同的静态成员函数:一个采用指向const的指针参数,并采用指向非const的参数.我想避免代码重复.
在阅读了一些堆栈溢出问题(这些都是关于非静态成员函数的)之后我想出了这个:
class C {
private:
static const type* func(const type* x) {
//long code
}
static type* func(type* x) {
return const_cast<type*>(func(static_cast<const type*>(x)));
}
public:
//some code that uses these functions
};
Run Code Online (Sandbox Code Playgroud)
(我知道玩指针通常是一个坏主意,但我正在实现一个数据结构.)
我在libstdc ++中发现了一些如下所示的代码:
注意:这些代码不是成员函数
static type* local_func(type* x)
{
//long code
}
type* func(type* x)
{
return local_func(x);
}
const type* func(const type* x)
{
return local_func(const_cast<type*>(x));
}
Run Code Online (Sandbox Code Playgroud)
在第一种方法中,代码在一个带有指针到const参数的函数中.
在第二种方法中,代码在一个函数中,该函数接受指向非const的参数.
通常应该使用哪种方法?两个都正确吗?
好的,我做了一些研究,显然在这个主题上有很多关于SO的重复问题,仅举几例:
但是我忍不住再提一下,因为
auto -typed返回值,我实际上是复制函数体,唯一的区别是const函数限定符.const版本和非const版本可能返回彼此完全不相容的类型.在这种情况下,斯科特迈耶斯的const_cast习语,以及"非const功能返回非const"技术都不会起作用.举个例子:
struct A {
std::vector<int> examples;
auto get() { return examples.begin(); }
auto get() const { return examples.begin(); }
}; // Do I really have to duplicate?
// My real-world code is much longer
// and there are a lot of such get()'s
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下,auto get()返回一个iteratorwhile auto get() const返回一个const_iterator,并且两个不能相互转换(我知道erase(it,it) …
我有两个成员
A &B::GetA (int i)
{
return *(m_C[m_AtoC[i]]);
}
const A &B::GetA (int i) const
{
return *(m_C[m_AtoC[i]]);
}
Run Code Online (Sandbox Code Playgroud)
现在我只是重复代码,但可能存在很好的方法来做到这一点.我绝对不想处理从const到非const的类型转换.
编辑:所以我想打电话给另一个成员,以避免代码重复.
struct BananaHolder
{
vector<Banana>& getBananas();
const vector<Banana>& getBananas() const;
};
Run Code Online (Sandbox Code Playgroud)
我的课程充满了这种重复。
有没有更干净、更优雅的替代方案?
c++ getter c++11 function-qualifier explicit-object-parameter
const_cast 可以用于创建已实现方法的非常量版本吗?我想我看到了一些类似的内容(建议使用 const 方法来完成实际工作),但我不太确定它应该如何工作。
Value& const search(key) const {
// find value with key
return value;
}
Value& search(key) {
return const_cast<Value&>(search(key));
}
Run Code Online (Sandbox Code Playgroud)
如果不是这样,那么在没有代码重复的情况下创建非常量函数的推荐方法是什么?
在这篇文章后,我实现了一个类似的访问器
template<class T> class qv {
virtual const T& operator[](int i) const = 0;
T& operator[](int i) { return const_cast<T&>(static_cast<const qv*>(this)->operator[](i)); }
};
template<class T> class qq : public qv<T> {
public:
const T& operator[](int i) const override { return this->data[i]; }
protected:
T data[5];
};
Run Code Online (Sandbox Code Playgroud)
但assignment of read-only location在尝试做类似的事情时得到一个:
int main(int argc, char** argv) {
qq<int> q;
q[3] = 2; // read-only location compile error, g++ 6.3
}
Run Code Online (Sandbox Code Playgroud)
这是导致问题的继承,但我不知道是什么或为什么.顺便说一下,如果我使用静态或const_cast作为上面的内部演员是否重要?
考虑以下代码:
int g(std::vector<int>&, size_t);
int f(std::vector<int>& v) {
int res = 0;
for (size_t i = 0; i < v.size(); i++)
res += g(v, i);
return res;
}
Run Code Online (Sandbox Code Playgroud)
编译器无法优化v.size()循环内的评估,因为它无法证明里面的大小不会改变g。用GCC 9.2 -O3和x64 生成的程序集是:
.L3:
mov rsi, rbx
mov rdi, rbp
add rbx, 1
call g(std::vector<int, std::allocator<int> >&, unsigned long)
add r12d, eax
mov rax, QWORD PTR [rbp+8] // load a poniter
sub rax, QWORD PTR [rbp+0] // subtract another pointetr
sar rax, 2 // result * …Run Code Online (Sandbox Code Playgroud) 假设我有一个结构体,它有一个名称和一些与之关联的值:
struct Season {
std::string name;
// Mean temperature over the season
double meanTemperature;
// Days since the start of year when it's strongest
float strongestAt;
// Fraction of a year it applies to, compared to other seasons
float yearFraction;
}
Run Code Online (Sandbox Code Playgroud)
本课程描述了每年的一个季节。假设我有一个它们的集合,它填充了一整年:
// made up method that is supposed to find a season (I don't use it in real code)
int findIndex(const std::vector<Season>& in, std::function<bool(const Season&)>);
class SeasonCollection
{
public:
const Season* GetSeason(const std::string& name) const
{
const int index …Run Code Online (Sandbox Code Playgroud) 好吧,我现在正在重构我很久以前制作的一个课程.该类是容器类型.
许多函数可以利用类结构的优点,因此实现为成员函数.然而现在它似乎是很多看似"相同"的功能,即"查找"功能:
iterator find(ITEM)
const_iterator find(ITEM) const;
iterator find_if(ITEM, PRED)
const_iterator find_if(ITEM, PRED) const;
Run Code Online (Sandbox Code Playgroud)
4个"函数"来描述几乎相同(并且每个版本的代码几乎相同).更新课程时这变得非常繁琐,我必须确保每个版本都升级.有没有办法更好地处理这些事情?类CAN中的其他一些函数可能需要2个谓词,这意味着我突然有8个函数需要管理.
我试过调用"常量版本的非常量版本",但这显然不起作用.
那么如何处理这些事情呢?只需咬紧牙关并写下来?
编辑:只是为了通知:我的数据结构类似于"树".每个"对象"包含数据(查找搜索)和带有子树的"列表".find函数在树(和子子树)的所有子树上递归递归. - 就像人们在搜索树时所期望的那样.
由于没有明确的"结束"或"开始"迭代器到这样的树,使用std :: find不会产生正确的功能.
c++ ×10
const ×5
c++11 ×2
constants ×2
c++14 ×1
code-reuse ×1
const-cast ×1
containers ×1
getter ×1
iterator ×1
loops ×1
methods ×1
optimization ×1
overloading ×1
return ×1
vector ×1