Tag: 语言律师

reinterpret_cast创build一个普通的默认构造对象

cppreference †指出: 具有普通默认构造函数的对象可以通过在任何适当alignment的存储上使用reinterpret_cast来创build,例如,在使用std::malloc分配的std::malloc 。 这意味着以下是明确的代码: struct X { int x; }; alignas(X) char buffer[sizeof(X)]; // (A) reinterpret_cast<X*>(buffer)->x = 42; // (B) 三个问题如下: 那个报价是正确的吗? 如果是的话,那么X的使用寿命到了什么时候? 如果在线(B) ,它是否被视为获取存储的本身? 如果在线(A) ,如果在(A)和(B)之间有一个分支会有条件地构build一个X或其他吊舱, Y ? 在这方面,C ++ 11和C ++ 1z之间有什么变化吗? †请注意,这是一个旧的链接。 这个问题的措辞已经改变了。 它现在写道: 然而,与C不同的是,具有简单默认构造函数的对象不能通过简单地重新解释适当alignment的存储来创build,例如使用std::malloc分配的std::malloc :placement-new需要正式引入一个新对象,并避免潜在的未定义行为。

如果(条件)在C ++中尝试{…}是否合法?

例如: if (true) try { // works as expected with both true and false, but is it legal? } catch (…) { // … } 换句话说, 在if条件之后放置try-block是否合法?

C ++ 11&C ++ 14中“bsearch”的规范是否有缺陷?

从我对这个问题的回答开始,在C ++ 11和C ++ 14中: [C++11, C++14: 25.5/2]:内容与标准C库头<stdlib.h> ,但有以下几点例外: [C++11, C++14: 25.5/3]:函数签名: bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); 被两个声明所取代: extern "C" void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); extern "C++" void *bsearch(const void *key, const […]

从C ++中的私有模板类inheritance构造函数

为什么D类编译,但C类不? class A { public: A(int) {} }; template <class T> class B : private T // Note: private base class { public: using T::T; }; class C : public B<A> { public: C() : B<A>(123) {} // Error: 'class AA::A' is inaccessible }; // within this context using BA = B<A>; class D : […]

为什么lambda转换为值为true的布尔值?

#include <iostream> void IsTrue(const bool value) { if (value) { std::cout << "value is True!\n"; } } int main() { IsTrue([]() { ; /* some lambda */ }); return 0; } 输出: value is True! 为什么lambda在GCC和Clang上评估为true ? MSVC不能build立这个(不能转换lambda到布尔)。 这是一个编译器错误? 或者标准的哪一段允许这样做?

是typedef之间的types和别名符合标准?

我偶然发现了typedef关键字在types和别名之间的代码 int typedef INT; 它在gcc和clang中编译( 现场示例 )。 我对标准的理解不是很好。 所以我的问题是:这个标准是一致的吗? 我可以依靠编译器来支持它吗?

下面的第一个代码片段编译,但第二个没有。 为什么?

下面的代码片段编译( 演示 ): struct A{ int i = 10; }; int main() { struct A{ int i = 20; }; struct A; struct A a; } 但是这不是: struct A{ int i = 10; }; int main() { // struct A{ int i = 20; }; struct A; struct A a; } 我可以看到,答案可能是由标准中的这些段落给出的: [basic.lookup.elab] / 2和[basic.scope.pdecl] […]

在C ++ 11中,“i + = ++ i + 1”是否performance出未定义的行为?

这个问题出现在我正在阅读(答案)时,为什么我在C ++ 11中定义了明确的i ++ I + 1? 我收集的微妙的解释是(1)expression式++i返回一个左值,但是+ prvalues作为操作数,所以必须执行从左值到左值的转换; 这涉及获得该左值的当前值(而不是一个比旧的值多一个),因此必须在增量的副作用(即,更新i ) 后sorting(2)该赋值的LHS也是因此其价值评估不涉及获取i的当前价值; 而这个值的计算与RHS的值计算是不一致的,这就不存在问题。(3)赋值本身的值计算涉及更新i (再次),而是在RHS的值计算之后进行sorting,因此在先给i更新; 没问题。 好吧,那里没有UB。 现在我的问题是,如果将assigment操作符从=改成+= (或类似的操作符),会怎样。 expression式i += ++i + 1的评估是否会导致未定义的行为? 正如我所看到的那样,这个标准似乎在这里相互矛盾。 由于+=的LHS仍然是一个左值(而其RHS仍然是一个值),就上面(1)和(2)而言,同样的推理也适用。 在+=上操作数的评估中没有未定义的行为。 至于(3),复合赋值的操作+= (更准确地说是该操作的副作用;如果需要的话,它的值计算在任何情况下都在其副作用之后被sorting)现在必须同时获取当前值i , 然后 (明显地按顺序排列,即使标准没有明确说明,否则评估这样的操作符总是会调用未定义的行为)添加RHS并将结果存回i 。 如果这些操作在++副作用下没有被确定,那么这两个操作都会给出未定义的行为,但是正如上面所讨论的( ++的副作用是在给出+=操作符的RHS的值计算之前进行sorting的,哪个值计算在该复合赋值操作之前被sorting),情况并非如此。 但是另一方面,标准还表示E += F相当于E = E + F ,只是(左值)E只被评估一次。 现在在我们的例子中, 作为左值的i (这是E在这里是什么)的值计算不涉及需要与其他动作sorting的任何事情,因此做一次或两次都没有区别; 我们的expression应严格等于E = E + F 但是这是问题。 很明显,评估i = i + […]

增加一个空指针定义良好?

在做指针算术的时候,有很多未定义/未指定行为的例子 – 指针必须指向同一个数组(或者结束时),或者在同一个对象中,限制什么时候可以根据上面的方法进行比较/操作等等 以下操作是否定义良好? int* p = 0; p++;

是&errno合法C?

每7.5, [errno]扩展为一个可修改的lvalue175),其types为int,其值由多个库函数设置为正确的错误编号。 errno是macros还是用外部链接声明的标识符是未指定的。 如果为了访问实际对象而抑制macros定义,或者程序定义了名称为errno的标识符,则行为是不确定的。 macroserrno不一定是一个对象的标识符。 它可能会扩展为由函数调用(例如,* errno())产生的可修改的左值。 我不清楚这是否足以要求&errno不是违反约束。 C语言有左值(比如register-storage-classvariables;但是这些variables只能是自动的,所以errno不能被定义成这样), &操作符是违反约束条件的。 如果&errno是合法的C,是否需要保持不变?