考虑以下功能:
void func(bool& flag)
{
if(!flag) flag=true;
}
Run Code Online (Sandbox Code Playgroud)
在我看来,如果flag有一个有效的布尔值,这相当于无条件设置它true,如下所示:
void func(bool& flag)
{
flag=true;
}
Run Code Online (Sandbox Code Playgroud)
然而,gcc和clang都没有这样优化它 - 都在-O3优化级别生成以下内容:
_Z4funcRb:
.LFB0:
.cfi_startproc
cmp BYTE PTR [rdi], 0
jne .L1
mov BYTE PTR [rdi], 1
.L1:
rep ret
Run Code Online (Sandbox Code Playgroud)
我的问题是:只是代码太特殊flag而不关心优化,或者是否有任何好的理由为什么这样的优化是不希望的,因为它不是一个参考volatile?看来这可能是唯一的原因是,flag可以在某种程度上具有非true-或- false在阅读它的点不未定义行为的价值,但我不知道这是否是可能的.
我找不到太多的信息const_cast.我能找到的唯一信息(在Stack Overflow上)是:
将
const_cast<>()用于添加/删除变量的常量(岬)(或挥发性岬).
这让我很紧张.可能const_cast会导致意外行为?如果是这样,什么?
或者,什么时候可以使用const_cast?
我偶然发现了这篇Reddit 帖子,它是对以下代码片段的一个玩笑,
void f(int& x) {
if (x != 1) {
x = 1;
}
}
void g(int& x) {
x = 1;
}
Run Code Online (Sandbox Code Playgroud)
说这两个函数不等同于“编译器”。我确信任何主要的 C++ 编译器都会将条件赋值优化为无条件存储,从而为f和发出相同的汇编代码g。
谁能向我解释为什么会这样?
我的想法是:无条件存储很可能会更快,因为无论如何我们都必须访问内存来读取比较值,并且分支代码会给分支预测器带来压力。此外,编译器不应将存储视为副作用(AFAIK),即使后续内存访问可能会更快或更慢,具体取决于是否f由于缓存局部性而采用分支。
那么编译器就无法弄清楚这一点吗?虽然证明f和 的等价性g可能并不容易,但我觉得这些编译器能够解决更困难的问题。那么我可能错了,这些功能毕竟不相等,或者这里发生了什么?
我的类中有一个私有变量Student定义为:
const int studentNumnber;
Run Code Online (Sandbox Code Playgroud)
我正在尝试为学生编写一个复制构造函数,我需要抛弃constness来执行此操作,遗憾的是我不明白如何使用std::const_cast.
这是我在我的复制构造函数中尝试做的事情:
Student(const Student & s)
: Person(p.getName(), p.getEmailAddress(), p.getBirthDate()), school(0), studentNumber(0) {
school = new char[strlen(s.school) + 1];
strcpy_s(school, strlen(s.school) + 1, s.school);
const_cast<int*>(this)->studentNumber = s.studentNumber;
//studentNumber = s.studentNumber);
}
Run Code Online (Sandbox Code Playgroud)
这不起作用......我不确定这样做的语法是什么.
考虑以下简单程序:
#include <cstring>
#include <cstdio>
#include <cstdlib>
void replace(char *str, size_t len) {
for (size_t i = 0; i < len; i++) {
if (str[i] == '/') {
str[i] = '_';
}
}
}
const char *global_str = "the quick brown fox jumps over the lazy dog";
int main(int argc, char **argv) {
const char *str = argc > 1 ? argv[1] : global_str;
replace(const_cast<char *>(str), std::strlen(str));
puts(str);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
它在命令行上使用(可选)字符串并打印它,并/替换为字符_.该替换功能由c_repl功能1实现.例如, …
我有一个带有模板参数的类,我想调用它的方法.它看起来像这样:
template <typename T>
class Foo {
public:
void doSomething() {
for (auto& t: ts) {
t.doSomething();
}
}
private:
std::vector<T> ts;
};
Run Code Online (Sandbox Code Playgroud)
这是有效的,但我想制作doSomething()const如果T它本身是const(假设它也是T::doSomething()const).我找到了一个可能的解决方案(基于这个问题),但我不喜欢它.
template <bool enabled = std::is_const<T>::value>
typename std::enable_if<enabled, void>::type
doSomething() const {
for (auto& t: ts) {
t.doSomething();
}
}
template <bool enabled = !std::is_const<T>::value>
typename std::enable_if<enabled, void>::type
doSomething() {
for (auto& t: ts) {
t.doSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但它有代码重复.有什么办法可以避免吗?
我知道const应该谨慎地进行抛弃- 并且任何const从初始const对象中删除-ness 然后修改对象的尝试都会导致未定义的行为.如果我们想删除const-ness以便我们可以调用一个不修改对象的非const函数,该怎么办?我知道我们应该实际标记这样的功能const,但是假设我使用的是一个没有const可用版本的"坏"代码.
那么,总结一下,下面的代码是"安全的"吗?我的猜测是,只要你没有最终修改对象你就可以了,但我不是百分百肯定.
#include <iostream>
struct Foo
{
void f() // doesn't modify the instance, although is not marked const
{
std::cout << "Foo::f()" << std::endl;
}
};
int main()
{
const Foo foo;
const_cast<Foo&>(foo).f(); // is this safe?
}
Run Code Online (Sandbox Code Playgroud) 如果我做:
const char* const_str = "Some string";
char* str = const_cast<char*>(const_str); // (1)
str[0] = "P"; // (2)
Run Code Online (Sandbox Code Playgroud)
哪个(哪一行)确实是未定义的行为?
我一直在搜索这个问题,但没有找到任何明确而准确的答案(或者至少没有我能理解的答案).
还相关:如果我使用提供这种功能的外部库:
// The documentation states that str will never be modified, just read.
void read_string(char* str);
Run Code Online (Sandbox Code Playgroud)
可以写下这样的东西:
std::string str = "My string";
read_string(const_cast<char*>(str.c_str()));
Run Code Online (Sandbox Code Playgroud)
因为我知道肯定read_string()会从未尝试写str?
谢谢.