更新,见下文!
我听说并读过C++ 0x允许编译器为以下代码段打印"Hello"
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
它显然与线程和优化功能有关.在我看来,这可能让许多人感到惊讶.
有人能够很好地解释为什么必须允许这样做吗?作为参考,最新的C++ 0x草案说明了6.5/5
在for语句的情况下,在for-init语句之外的循环,
- 不调用库I/O函数,和
- 不访问或修改易失性对象,以及
- 不执行同步操作(1.10)或原子操作(第29条)
可以通过实现来假设终止.[注意:这是为了允许编译器转换,例如删除空循环,即使无法证明终止也是如此. - 结束说明]
编辑:
这篇富有洞察力的文章谈到了标准文本
不幸的是,没有使用"未定义的行为".但是,只要标准说"编译器可以假设P",就暗示具有非-P属性的程序具有未定义的语义.
这是正确的,是否允许编译器为上述程序打印"Bye"?
这里有一个更有见地的线索,这是关于C的类似改变,由Guy完成上述链接文章开始.在其他有用的事实中,他们提出了一个似乎也适用于C++ 0x的解决方案(更新:这将不再适用于n3225 - 见下文!)
endless:
goto endless;
Run Code Online (Sandbox Code Playgroud)
看来,编译器不允许优化它,因为它不是循环,而是跳转.另一个人总结了C++ 0x和C201X的建议更改
通过编写一个循环,程序员断言或者环路不可见的东西的行为(执行I/O,访问volatile对象,或执行同步或原子操作), 或者,它最终会终止.如果我通过编写一个没有副作用的无限循环来违反这个假设,我对编译器撒谎,而我的程序的行为是未定义的.(如果我很幸运,编译器可能会警告我.)语言不提供(不再提供?)表达无可见行为的无限循环的方法.
2011年3月3日更新为n3225:委员会将案文移至1.10/24并说
实现可以假定任何线程最终将执行以下操作之一:
- 终止,
- 调用库I/O函数,
- 访问或修改易失性对象,或
- 执行同步操作或原子操作.
的goto
把戏,不工作了!
例如:
Beta_ab&&
Beta::toAB() const {
return move(Beta_ab(1, 1));
}
Run Code Online (Sandbox Code Playgroud) 我今天查看了一些Java代码,我发现了一些奇怪的语法:
public class Sample {
public int get()[] {
return new int[]{1, 2, 3};
}
}
Run Code Online (Sandbox Code Playgroud)
我认为无法编译并想修复我认为的错字,但后来我记得Java编译器确实接受了它!
有人可以帮我理解这是什么意思吗?它是一组函数吗?
我听说const
意味着线程安全的C++ 11.真的吗?
这是否意味着const
现在是等效的Java的synchronized
?
他们的关键字用完了吗?
在C++中,可以static
在翻译单元中使用关键字来影响符号的可见性(变量或函数声明).
在n3092,这被弃用了:
附件D.2 [depr.static]
在命名空间范围内声明对象时,不推荐使用static关键字(见3.3.6).
在n3225中,这已被删除.
它确实强调,为了与C兼容(以及将C程序编译为C++的能力),弃用令人讨厌.但是,直接将C程序编译为C++本身就是一种令人沮丧的经历,所以我不确定它是否值得考虑.
有谁知道为什么它被改变了?
的C++ 0x将会使下面的代码和类似代码形成不良的,因为它需要一个所谓的收缩转换的double
一个int
.
int a[] = { 1.0 };
Run Code Online (Sandbox Code Playgroud)
我想知道这种初始化是否在现实代码中被大量使用.这个改变将破坏多少代码?如果您的代码受到影响,是否需要在代码中修复此问题?
供参考,参见n3225的8.5.4/6
缩小转换是隐式转换
- 从浮点类型到整数类型,或
- 从long double到double或float,或从double到float,除非source是常量表达式,转换后的实际值在可以表示的值范围内(即使它不能精确表示),或者
- 从整数类型或无范围枚举类型到浮点类型,除非源是常量表达式,转换后的实际值将适合目标类型,并在转换回原始类型时生成原始值,或者
- 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,除非source是常量表达式,并且转换后的实际值将适合目标类型并且将在生成原始值时生成原始值转换回原始类型.
我以前从未见过它.我认为这是":: sample"的拼写错误,但是当我看到它实际编译时我很困惑.有人能帮我找到吗?我不认为这是一个goto
标签.
void f() {
class: sample {
// there were some members declared here
} x;
}
Run Code Online (Sandbox Code Playgroud) 我想对特定包含文件直接或间接包含的所有文件禁用特定警告.例如,我想禁用警告"你正在为字符串文字指定一个字符串文字*",包括a所包含的文件所包含的所有文件或文件#include <bar/*>
(在我的情况下,明星意味着"任何东西可能在这里").
原因是,我必须编程的一些人不能使用"const",所以最后我得到很多关于特定字符串文字滥用的警告.我想忽略来自他们代码的成千上万的警告,所以我可以专注于我自己的代码中的错误并修复它们.
我使用的是英特尔C++和GCC.我的一些伙伴使用clang,所以我很乐意听到解决方案.
我有这个问题,我之前想过这个问题,但认为回答并非易事
int x = x + 1;
int main() {
return x;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果程序的行为是有效的,那么它是否被定义或未定义.如果定义了,那么x
已知的值是main
多少?
在我正在研究的其中一个项目中,我看到了这段代码
struct Base {
virtual ~Base() { }
};
struct ClassX {
bool isHoldingDerivedObj() const {
return typeid(1 ? *m_basePtr : *m_basePtr) == typeid(Derived);
}
Base *m_basePtr;
};
Run Code Online (Sandbox Code Playgroud)
我从来没有见过这样的typeid
用法.为什么它会做那种奇怪的舞蹈?:
,而不仅仅是做typeid(*m_basePtr)
?有什么理由吗?Base
是一个多态类(带有虚拟析构函数).
编辑:在这个代码的另一个地方,我看到这个,它似乎是等价的"多余的"
template<typename T> T &nonnull(T &t) { return t; }
struct ClassY {
bool isHoldingDerivedObj() const {
return typeid(nonnull(*m_basePtr)) == typeid(Derived);
}
Base *m_basePtr;
};
Run Code Online (Sandbox Code Playgroud)