读取未初始化的变量会导致未定义的行为,例如
#include <iostream>
int main()
{
int a;
std::cout << a << std::endl; // undefined behavior
}
Run Code Online (Sandbox Code Playgroud)
有人可以对这个事实给出正式的解释吗?
(这都是Python 3.5.2上的)
在PEP 448的底部,我看到:
函数调用中不带括号的推导式(例如 )
f(x for x in it)
已经有效。
这很有趣。如果我定义以下函数:
def f(a, b, c):
return a + b + c
Run Code Online (Sandbox Code Playgroud)
那么这个措辞让我这么认为f(thing for thing in [1, 2, 3]) == 6
。但实际上,我得到:
>>> f(thing for thing in [1, 2, 3])
TypeError: f() missing 2 required positional arguments: 'b' and 'c'
Run Code Online (Sandbox Code Playgroud)
即整个生成器表达式作为 传递a
。
那么PEP 448中的这句话是什么意思呢?只是您可以传递生成器表达式作为参数吗?
[expr.const] p9定义转换后的常量表达式为:
\n\n\n\n\nA\xc2\xa0 conversionconstant expression \xc2\xa0of type\xc2\xa0
\nT
\xc2\xa0是一个表达式,隐式转换为类型\xc2\xa0T
,其中转换后的表达式是常量表达式,隐式转换序列仅包含 [。 ..]
在以下示例中:
\n\nconst int a = 42;\nint b[a];\n
Run Code Online (Sandbox Code Playgroud)\n\n该标准没有指定应用于的转换是否a
是表达式求值的一部分(事实上,它们被认为是完整表达式的一部分,即初始化声明符),并且如果不指定这一点,它实际上意味着任何类型的泛左值表达式int
都是转换后的常量表达式,因为转换不是结果纯右值评估的一部分(应用转换,产生纯右值,然后评估该纯右值)。是我错了,还是措辞有缺陷?
我想知道 .Net 中是否曾经或仍然存在过这种情况。
使用 exp += val 而不是 exp = exp + val。由于 exp 可以任意复杂,这可能会导致大量不必要的工作。这迫使 JIT 评估 exp 的两个副本,但很多时候这是不需要的。第一个语句的优化效果比第二个语句好得多,因为 JIT 可以避免对 exp 求值两次。
这是来自 codeproject 中的一篇古老文章。
cpp中还有另外一个:
但是,复合赋值表达式并不等同于扩展版本,因为复合赋值表达式仅对 expression1 求值一次,而扩展版本对 expression1 求值两次:在加法运算和赋值运算中。
An ascending sort callback function for qsort
and bsearch
on an array of int
could look like this:
int ascending(const void *o1, const void *o2) {
int a = *(const int *)o1;
int b = *(const int *)o2;
return a < b ? -1 : 1;
}
Run Code Online (Sandbox Code Playgroud)
Yet this function seems to violate the constraint on the compar
function as specified in the C Standard:
7.22.5.2 The
qsort
functionSynopsis
Run Code Online (Sandbox Code Playgroud)#include <stdlib.h> void qsort(void *base, size_t nmemb, size_t size, int …
在不借助 boost.iterator 等库的帮助下创建 C++20 之前的新迭代器时,有必要指定类型别名difference_type
、value_type
、pointer
和。
根据cppreference ,对于 C++20,只需要指定和reference
iterator_category
difference_type
value_type
这很棒!但是为什么这 3 个别名有默认值呢?
有两件事我不明白(其中一件事在我看来像是一个疏忽):
value_type
为什么和没有默认值difference_type
?使用类似的东西std::remove_reference_t<reference>
作为默认值难道没有意义吗value_type
?作为随机访问迭代器的默认设置difference_type
,使用采用两个迭代器的运算符的结果类型可以说是有意义的-
。contiguous_iterator_tag
. 就像与input_iterator_tag
vsforward_iterator_tag
一样,我不明白编译器如何正确区分连续迭代器和随机访问迭代器,我想这就是它显然从不选择的原因contiguous_iterator_tag
。这是故意的吗?将输入迭代器错误分类为前向迭代器似乎也有些危险,那么为什么不要求程序员自己指定此别名呢?iterator_category
程序员已经明确声明了另一个类别,但默默地生成一个值是否是一个好主意,并且为iterator_category
它生成一个与看起来完全不同的值concept
也很奇怪。考虑这个不切实际的例子:#include <iostream>
#include <iterator>
// With the == operator, this is an input iterator, but nothing else.
struct WeirdIterator {
// Not an output iterator because …
Run Code Online (Sandbox Code Playgroud) 简单的问题:如果一元运算符的优先级接近最高,那么为什么#
and##
运算符的计算顺序是未指定的?与 C 和 C++ 相关。
C11(6.10.3.2 # 运算符):
# 和 ## 运算符的计算顺序未指定。
C++,N4713(19.3.2 # 运算符):
# 和 ## 运算符的计算顺序未指定。
在C++中,当对象的析构函数被调用时,它首先调用子类的析构函数,然后是父类的析构函数,这与构造过程相反。但为什么?这似乎是一个简单的问题,但我还没有在互联网上找到令人满意的答案。有人可以解释以这种顺序进行破坏的必要性吗?
上下文:C 编译器在实现一致的同时故意不支持某些功能。可以吗?
\n一些例子。下面的所有编译器都是一致的实现(__STDC__
定义为1
)。然而:
gcc 不支持#pragma STDC FENV_ACCESS
并出现问题warning: ignoring \xe2\x80\x98#pragma STDC FENV_ACCESS\xe2\x80\x99 [-Wunknown-pragmas]
。然而, fenv.h 是一个标准头文件,#pragma STDC FENV_ACCESS ON
标准要求支持 ,因为是on-off-switch :ON
中的选择之一。ON OFF DEFAULT
msvc 不支持#pragma STDC FP_CONTRACT
,而是支持它自己的版本#pragma fp_contract ( { on | off } )
。但是,标准版本是#pragma STDC FP_CONTRACT { ON | OFF | DEFAULT }
.
Cygwin 上的 gcc:sscanf 不处理十六进制浮点输入。libc 是标准的一部分。
\n问题:是否允许实现故意提供有限的功能(或其自己的此类功能版本),同时仍然符合实现? …
从 C17 开始,递减指向数组第一个元素的指针是未定义的行为。这个答案引用了C17标准的说法
C17 6.5.6/8
如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则求值不会产生溢出;否则,行为是未定义的。
这是最早定义的标准吗?早期标准中如何定义此类操作?以前合法吗?
language-lawyer ×10
c++ ×5
c ×4
c17 ×2
.net ×1
c# ×1
c++17 ×1
c++20 ×1
c11 ×1
iterator ×1
optimization ×1
python ×1
python-3.x ×1
qsort ×1
sorting ×1