Questions tagged «language-lawyer»

有关编程语言和环境的正式或权威规范的复杂性的问题。

3
什么时候应该使用@classmethod?什么时候应该使用def method(self)?
在集成我以前从未使用过的Django应用程序时,我发现了用于定义类中函数的两种不同方式。作者似乎非常有意地使用了它们。第一个是我自己经常使用的: class Dummy(object): def some_function(self,*args,**kwargs): do something here self is the class instance 另一个是我不使用的,主要是因为我不知道何时使用它,以及什么用途: class Dummy(object): @classmethod def some_function(cls,*args,**kwargs): do something here cls refers to what? 在Python文档中,classmethod装饰器的解释如下: 类方法将类作为隐式第一个参数接收,就像实例方法接收实例一样。 所以我想cls指的是Dummy自己(而class不是实例)。我不完全理解为什么会这样,因为我总是可以这样做: type(self).do_something_with_the_class 这仅仅是为了清楚起见,还是我错过了最重要的部分:没有它就无法完成的怪异而令人着迷的事情?

6
为什么在C ++中引用不是“ const”?
我们知道,“常量变量”表示一旦分配,就不能更改该变量,如下所示: int const i = 1; i = 2; 上面的程序无法编译;gcc提示错误: assignment of read-only variable 'i' 没问题,我可以理解,但是以下示例超出了我的理解范围: #include<iostream> using namespace std; int main() { boolalpha(cout); int const i = 1; cout << is_const<decltype(i)>::value << endl; int const &ri = i; cout << is_const<decltype(ri)>::value << endl; return 0; } 它输出 true false …

2
为什么在Roslyn中使用异步状态机类(而不是结构)?
让我们考虑一下这个非常简单的异步方法: static async Task myMethodAsync() { await Task.Delay(500); } 当我使用VS2013(Roslyn之前的编译器)进行编译时,生成的状态机是一个结构。 private struct <myMethodAsync>d__0 : IAsyncStateMachine { ... void IAsyncStateMachine.MoveNext() { ... } } 当我使用VS2015(Roslyn)进行编译时,生成的代码是这样的: private sealed class <myMethodAsync>d__1 : IAsyncStateMachine { ... void IAsyncStateMachine.MoveNext() { ... } } 如您所见,罗斯林生成一个类(而不是一个结构)。如果我没有记错的话,旧编译器中异步/等待支持的第一个实现(我猜是CTP2012)也会生成类,然后出于性能原因将其更改为struct。(在某些情况下,您可以完全避免装箱和分配堆…)(请参阅此) 有谁知道为什么在罗斯林再次改变了这一点?(对此我没有任何问题,我知道此更改是透明的,不会更改任何代码的行为,我很好奇) 编辑: 来自@Damien_The_Unbeliever(和源代码:))的答案可以解释一切。Roslyn的描述的行为仅适用于调试构建(由于注释中提到了CLR限制,因此需要这样做)。在Release中,它还会生成一个结构(具有所有好处。)。因此,这似乎是一个非常聪明的解决方案,可以同时支持“编辑”和“继续”以及更好的生产性能。有趣的东西,谢谢大家参加!



3
包含未定义行为的源代码会使编译器崩溃合法吗?
假设我去编译一些编写不佳的C ++源代码,这些源代码会调用未定义的行为,因此(正如他们所说)“任何事情都可能发生”。 从C ++语言规范在“合格”编译器中认为可接受的角度来看,这种情况下的“任何情况”是否包括编译器崩溃(或窃取我的密码,或者在编译时出现异常或错误),或者未定义行为的范围专门限于生成的可执行文件运行时会发生什么?


3
自C ++ 17起,具有正确地址和类型的指针仍然始终是有效的指针吗?
(参考此问答)。 在C ++ 17标准之前,[basic.compound] / 3中包含以下句子: 如果类型T的对象位于地址A,则将其值为地址A的cv T *类型的指针指向该对象,而不管如何获取该值。 但是从C ++ 17开始,此句子已删除。 例如,我相信这句话使此示例代码已定义,并且由于C ++ 17,这是未定义的行为: alignas(int) unsigned char buffer[2*sizeof(int)]; auto p1=new(buffer) int{}; auto p2=new(p1+1) int{}; *(p1+1)=10; 在C ++ 17之前,p1+1持有的地址*p2并具有正确的类型,因此*(p1+1)是的指针*p2。在C ++ 17p1+1中,指针是一个end-the-end,因此它不是指向对象的指针,并且我相信它是不可引用的。 是对标准权利的这种修改的解释,还是有其他规则可以补偿所引用句子的删除?

2
在c ++ 0x中删除nullptr是否仍然安全?
在c++03它是很清楚,删除一个空指针没有任何效果。实际上,明确指出§5.3.5/2: 在这两种选择中,如果delete操作数的值为空指针,则该操作无效。 但是,在当前的草案中c++0x似乎缺少这句话。在草案的其余部分中,我只能找到一些句子,说明如果delete-expression的操作数不是空指针常量,会发生什么情况。是否仍在中定义删除空指针c++0x,如果是,在哪里? 笔记: 有大量的间接证据表明它仍然定义明确。 首先,有两个句子§5.3.5/2说明 在第一个替代方案(删除对象)中,删除操作数的值可以为空指针值,... 和 在第二个替代方案(删除数组)中,删除操作数的值可以为空指针值或... 这些都说操作数被允许为空,但是就其本身而言,实际上并没有定义发生什么情况。 其次,改变的含义delete 0是重大的突破性变化,标准委员会不太可能做出此特定更改。此外,在c++0x草案的兼容性附件(附件C)中没有提到这是一个重大更改。但是,附件C是资料性的部分,因此不涉及本标准的解释。 另一方面,要求删除空指针无效的事实意味着需要进行额外的运行时检查。在许多代码中,操作数永远不能为null,因此此运行时检查与零开销原则冲突。也许委员会只是决定改变行为,使标准c ++更符合该语言的既定设计目标。

4
C ++中逗号运算符与return的不同行为?
这(注意逗号运算符): #include <iostream> int main() { int x; x = 2, 3; std::cout << x << "\n"; return 0; } 输出2。 但是,如果return与逗号运算符一起使用,则: #include <iostream> int f() { return 2, 3; } int main() { int x; x = f(); std::cout << x << "\n"; return 0; } 输出3。 为什么逗号运算符的行为与众不同return?

6
new int;中的new是操作符吗?
new int;in等表达式int * x = new int;是一个新表达式。术语“新运算符”似乎可以与“新表达式”互换使用,例如在以下问题中:“新运算符”和“新运算符”之间的区别? 说new在新表达式中使用的关键字是运算符是否正确?为什么或者为什么不? 如果不是,是否有另一个理由来调用新表达式“ new operator”? 我很难找到构成操作员的权威定义。 我已经了解了为对象分配内存的new运算符和最终可能会调用的“ new expression”之间的区别operator new。

2
std :: ignore与结构化绑定?
序幕: std::tuple<int, int, int> f(); std::tuple<int, int, float, int> g(); C ++ 1z将引入结构化绑定的语法,这将使编写代替 int a, b, c; std::tie(a, b, c) = f(); 就像是 auto [a, b, c] = f(); 但是,std::tie还允许指定std::ignore忽略某些组件,例如: std::tie(a, b, std::ignore, c) = g(); 使用新的结构化绑定语法是否可以做类似的事情?如何运作?

9
永远不会执行的代码可以调用未定义的行为吗?
调用未定义行为(在此示例中为零)的代码将永远不会执行,程序是否仍是未定义行为? int main(void) { int i; if(0) { i = 1/0; } return 0; } 我认为这仍然是不确定的行为,但是我在标准中找不到任何证据来支持或否认我。 那么,有什么想法吗?

4
这个结构如何具有sizeof == 0?
有一则旧帖子要求一种sizeof可以返回的结构0。来自高声誉用户的一些高分答案说,按标准,类型或变量的大小不能为0。我同意100%。 但是,有一个新的答案介绍了此解决方案: struct ZeroMemory { int *a[0]; }; 我本来打算对它进行投票和评论,但是在这里花费的时间使我什至可以检查我100%确信的事情。所以......我既惊喜gcc和clang表现出同样的结果:sizeof(ZeroMemory) == 0。更重要的是,变量的sizeof是0: ZeroMemory z{}; static_assert(sizeof(z) == 0); // Awkward... 哇...? Godbolt链接 这怎么可能?

4
不同的编译器调用不同的强制转换运算符
考虑以下简短的C ++程序: #include <iostream> class B { public: operator bool() const { return false; } }; class B2 : public B { public: operator int() { return 5; } }; int main() { B2 b; std::cout << std::boolalpha << (bool)b << std::endl; } 如果在不同的编译器上进行编译,则会得到各种结果。使用Clang 3.4和GCC 4.4.7可以打印true,而Visual Studio 2013可以打印false,这意味着它们在调用不同的强制转换运算符(bool)b。根据标准,哪种行为正确? 以我的理解,operator bool()不需要转换,而operator …

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.