Tag: 语言律师

为什么这是一个无效的任务左侧?

为什么我可以做以下操作: var b1, b2; b1 = b2 = true; document.write(b1," ", b2); document.write("<br>"); b1 = !b2; document.write(b1," ", b2); document.write("<br>"); b1 = b2 = !true; document.write(b1," ", b2); 然而当我尝试下面的操作时,我收到一个ReferenceError: invalid assignment left-hand side ? var b1, b2; b1 = !b2 = true; document.write(b1," ", b2); 很显然,我不能这样做,但我找不到解释,为什么我不能。 有关错误的MDN开发人员指南指出: 有一个意想不到的任务。 例如,这可能是由于赋值运算符和比较运算符不匹配造成的。 当一个“=”符号给一个variables赋值时,“==”或“===”运算符比较一个值。 所有的赋值操作符都是单独工作的,所以为什么不能把它们合并成一个单独的操作/链接赋值呢?

使用受保护的析构函数dynamic分配类数组

如果我有一个类定义类似 class A { protected: ~A(){ } }; 那么我可以dynamic地分配个人以及对象的数组 A* ptr1 = new A; A* ptr2 = new A[10]; 但是,当我定义这个类的构造函数 class A { public: A(){} protected: ~A(){ } }; 那么我可以创build个人对象 A* ptr = new A; 但是当我尝试dynamic分配对象的数组 A* ptr = new A[10]; 编译器(gcc-5.1和Visual Studio 2015)开始抱怨A ::〜A()是不可访问的。 任何人都可以解释一下: 1-为什么在构造函数被定义和未定义的行为的差异。 2-当构造函数被定义为什么我被允许创build单个对象而不是对象数组。

未定义的行为如何未定义?

我不确定我是否理解未定义的行为会危害程序的程度。 比方说,我有这个代码: #include <stdio.h> int main() { int v = 0; scanf("%d", &v); if (v != 0) { int *p; *p = v; // Oops } return v; } 这个程序的行为是不是只针对v为非零的情况定义,或者即使v是零也不定义?

使用前面的函数参数声明新函数是否合法?

下面的代码用GCC干净地编译: void func(int arg1, decltype(arg1) arg2) { (void)arg2; } int main(){} 我用这个命令来编译: g++ -std=c++14 test.cpp -o test -pedantic-errors -Wall -Wextra 但是在函数声明中使用这个参数看起来很奇怪。 它实际上在标准C ++中是否有效,还是GCC扩展?

为什么不能重载类模板?

读这个问题让我怀疑:是否有一个技术原因不允许类模板重载? 通过重载,我的意思是有几个相同名称的模板,但不同的参数,例如 template <typename T> struct Foo {}; template <typename T1, typename T2> struct Foo {}; template <unsigned int N> struct Foo {}; 编译器pipe理处理重载的函数和函数模板,是不是可以应用类模板相同的技术(例如名称修改)? 起初,我认为也许这会在单独使用模板标识符时造成一些模糊性问题,但唯一可能发生的情况是将其作为模板模板parameter passing,因此可以使用参数的types来select适当的超载: template <template <typename> class T> void A {}; template <template <unsigned int> class T> void B {}; A<Foo> a; // resolves to Foo<T> B<Foo> b; // resolves to Foo<N> […]

在C ++中浮点加法是否可交换?

对于浮点值,保证a + b == b + a ? 我相信这在IEEE754中是有保证的,但是C ++标准没有规定必须使用IEEE754。 唯一相关的文本似乎来自[expr.add]#3: 二元运算符的结果是操作数的总和。 math运算“sum”是可交换的。 然而,math运算“sum”也是联想的,而浮点加法绝对不是联想的。 所以,在我看来,我们不能断定math中“sum”的交换性意味着这个引用在C ++中指定了交换性。

不相关的指针的平等比较可以评估为真?

关于==和!=运算符的C标准的 6.5.9节陈述如下: 2以下情况之一应为: 两个操作数都有算术types; 两个操作数都是指向兼容types的合格版本或非限定版本的指针; 一个操作数是一个指向对象types的指针,另一个是指向合格或不合格版本的void的指针; 要么 一个操作数是一个指针,另一个是一个空指针常量。 … 6 两个指针比较相等当且仅当两者都是空指针,都是指向同一个对象的指针(包括一个指向一个对象和一个子对象的指针)或者函数,都指向一个指向同一个对象的最后一个元素数组对象,或者一个指针指向一个数组对象的末尾,另一个指向不同数组对象的起始位置,该指针恰好紧跟地址空间中的第一个数组对象。 109) 7对于这些运算符而言, 指向不是数组元素的对象的指针的行为与指向长度为1的数组的第一个元素的指针相同,该对象的types是元素types。 脚注109: 109) 两个对象可能在内存中相邻,因为它们是大型数组中相邻的元素或结构的相邻成员之间没有填充,或者因为实现select将它们放置,即使它们不相关 。 如果之前的无效指针操作(如访问数组边界外)产生未定义的行为,后续比较也会产生未定义的行为。 这似乎表明您可以执行以下操作: int a; int b; printf("a precedes b: %d\n", (&a + 1) == &b); printf("b precedes a: %d\n", (&b + 1) == &a); 这应该是合法的,因为我们正在使用地址一个元素超过数组的末尾(在这种情况下是单个对象作为大小为1的数组对待),而不需要对其进行解引用。 更重要的是,如果一个variables紧跟在另一个variables的后面,那么这两个语句中的一个将被要求输出1 。 但是,testing似乎并没有解决这个问题。 鉴于以下testing程序: #include <stdio.h> struct s { int a; int […]

*((*(&array + 1)) – 1)可以安全地使用自动数组的最后一个元素吗?

假设我想获得大小未知的自动数组的最后一个元素。 我知道我可以使用sizeof运算符来获得数组的大小,并相应地得到最后一个元素。 正在使用*((*(&array + 1)) – 1)安全吗? 喜欢: char array[SOME_SIZE] = { … }; printf("Last element = %c", *((*(&array + 1)) – 1)); int array[SOME_SIZE] = { … }; printf("Last element = %d", *((*(&array + 1)) – 1)); 等等

a&b的结果是什么?

这很尴尬,但按比例运算符在C ++标准中定义如下(我的重点)。 通常的算术转换被执行; 结果是它的操作数的按位“与”function 。 该运算符仅适用于整数或非范围的枚举操作数。 这看起来对我来说毫无意义。 据我所知,“按位与function”在标准的任何地方都没有定义。 我知道AND函数很好理解,因此可能不需要解释。 “按位”这个词的含义也应该比较清楚:函数应用于其操作数的相应位。 但是,构成操作数的部分是不明确的。 是什么赋予了?

替代for循环语法

以下是C标准的一小部分( n1256 TC3 C99的第6.8.5节)。 迭代语句: while ( expression式 ) 语句 ( expression ) ; 用于 ( expression式opt ; expression式opt ; expression式opt ) 语句 用于 ( 声明 expression式opt ; expression式opt ) 语句 我最感兴趣的是最后一个陈述:( for ( declaration expression ; expression ) statement 。 6.8.5.1解释了for循环,但只提到了for ( clause-1 ; expression-2 ; expression-3 ) statement语法。 我按照这个语法写了一些代码,但都给了我语法错误。 例子: for (int i […]