Questions tagged «language-lawyer»

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


2
为什么在C ++ 20中的依赖类型之前不需要指定“ typename”?
这部分代码在C ++ 20中编译(使用gcc 10.1),而typename在依赖类型之前未使用关键字std::vector<T>::iterator。为什么要编译? #include <vector> template<typename T> std::vector<T>::iterator // Why does this not require "typename" before it? f() { return {}; } int main() { auto fptr = &f<int>; } 代码游乐场

2
可以在头文件中使用lambda违反ODR吗?
可以将以下内容写在头文件中: inline void f () { std::function<void ()> func = [] {}; } 要么 class C { std::function<void ()> func = [] {}; C () {} }; 我猜在每个源文件中,lambda的类型可能不同,因此std::function(target_type的结果中包含的类型会有所不同)。 尽管看起来像是一种常见模式并且是合理的做法,但这是否违反了ODR(一个定义规则)?第二个样本是否每次都违反ODR?或者仅在头文件中至少有一个构造函数时才违反?

3
std :: tuple sizeof,是否错过了优化?
我已经检查了所有主要的编译器,并且sizeof(std::tuple<int, char, int, char>)所有这些都是16。大概它们只是将元素按顺序放入元组中,因此由于对齐而浪费了一些空间。 如果元组在内部像这样存储元素:int, int, char, char,则其sizeof可以为12。 实现有可能执行此操作,还是该标准中的某些规则禁止这样做?

3
C ++函数中“返回”的确切时刻
这似乎是一个愚蠢的问题,但是return xxx;在一个函数中明确定义“执行”的确切时间吗? 请参见以下示例,以了解我的意思(此处直播): #include <iostream> #include <string> #include <utility> //changes the value of the underlying buffer //when destructed class Writer{ public: std::string &s; Writer(std::string &s_):s(s_){} ~Writer(){ s+="B"; } }; std::string make_string_ok(){ std::string res("A"); Writer w(res); return res; } int main() { std::cout<<make_string_ok()<<std::endl; } 我天真地希望发生的事情make_string_ok称为: 的构造函数res称为(值为resis "A") 的构造函数w称为 return res被执行。应该返回res的当前值(通过复制的当前值res),即"A"。 的析构函数 …

7
为什么未为C ++ 14数字分隔符选择空格字符?
从C ++ 14开始,由于n3781(它本身不能回答这个问题),我们可以编写如下代码: const int x = 1'234; // one thousand two hundred and thirty four 目的是改进这样的代码: const int y = 100000000; 并使其更具可读性。 下划线(_)字符已经由用户定义的文本采取了C ++ 11,和逗号(,)的本地化问题-许多欧洲国家令人困惑†以此作为小数点分隔符-和冲突与逗号操作,虽然我做的想知道允许使用可能破坏了哪些实际代码1,234,567。 无论如何,更好的解决方案似乎是空格字符: const int z = 1 000 000; 这些相邻的数字文字标记可以和字符串文字一样由预处理器连接: const char x[5] = "a" "bc" "d"; 相反,我们得到撇号('),我所知道的任何书写系统都没有使用它作为数字分隔符。 是否存在选择撇号而不是简单空格的原因? †之所以感到莫名其妙,是因为所有这些语言在文本内都保持着逗号的概念,即“分开”原本原子的句子,并用句号“终结”该句子-至少对我而言,这与逗号“分解”数字的整数部分,并用句号“终止”数字以准备小数输入。

11
遇到C的常见未定义/未指定行为是什么?[关闭]
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 7年前关闭。 改善这个问题 C语言中未指定行为的一个示例是对函数自变量的求值顺序。您可能不知道它可能是从左到右或从右到左。这将如何影响foo(c++, c)或foo(++c, c)获取评估。 还有哪些其他未说明的行为可能会使无意识的程序员感到惊讶?

2
为什么双分号是Python中的SyntaxError?
我知道分号在Python中是不必要的,但是它们可用于将多条语句填充到一行中,例如 >>> x = 42; y = 54 我一直认为分号等于换行符。因此,我很惊讶地得知(在Twitter上为Ned Batchelder),双分号是一个SyntaxError: >>> x = 42 >>> x = 42; >>> x = 42;; File "<stdin>", line 1 x = 42;; ^ SyntaxError: invalid syntax 我以为最后一个程序等于x = 42\n\n。我以为分号之间的语句被视为空行,禁止操作。显然不是。 为什么这是一个错误?

4
从理论上讲,C ++实现能否并行化两个函数参数的求值?
给定以下函数调用: f(g(), h()) 由于未指定函数参数的求值顺序(据我所知,仍然是C ++ 11中的情况),理论上可以执行g()并h()并行执行吗? 这种并行化只能踢都g和h已知相当琐碎(最明显的情况下,仅访问数据的本地,以自己的身体),以免引入并发问题,但是,除此之外,限制我什么都看不到,禁止它。 那么,标准允许吗?即使仅按常规规则进行? (在此答案中,Mankarse主张相反;但是,他没有引用该标准,而且我的通读[expr.call]并未显示任何明显的措辞。)

8
带重载算子的De Morgan定律优化
每个程序员都应该知道: (德摩根定律) 在某些情况下,为了优化程序,编译器可能会修改(!p && !q)为(!(p || q))。 这两个表达式是等效的,并且对第一个或第二个表达式的求值没有区别。 但是在C ++中,可能会重载运算符,而重载的运算符可能并不总是尊重此属性。因此,以这种方式转换代码实际上将修改代码。 当和重载时!,编译器是否应使用De Morgan定律?||&&



3
std :: vector(ab)使用自动存储
考虑以下代码段: #include <array> int main() { using huge_type = std::array<char, 20*1024*1024>; huge_type t; } 显然,它将在大多数平台上崩溃,因为默认堆栈大小通常小于20MB。 现在考虑以下代码: #include <array> #include <vector> int main() { using huge_type = std::array<char, 20*1024*1024>; std::vector<huge_type> v(1); } 令人惊讶的是它也崩溃了!追溯(使用最新的libstdc ++版本之一)指向include/bits/stl_uninitialized.h文件,我们可以在其中看到以下几行: typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; std::fill(__first, __last, _ValueType()); 调整大小的vector构造函数必须默认初始化元素,这就是它的实现方式。显然,_ValueType()临时崩溃会使堆栈崩溃。 问题是这是否是符合标准的实现。如果是,那么实际上意味着使用巨大类型的向量是非常有限的,不是吗?

2
复制构造函数中的C ++名称空间冲突
我有以下代码: namespace A { struct Foo { int a; }; } struct Foo { int b; }; struct Bar : public A::Foo { Bar(Foo foo) { c = foo.b; } int c; }; C ++编译器抱怨“ c = foo.b”,因为A :: Foo没有名为b的成员。如果我用:: Foo更改Bar参数的类型,它将起作用。 我的问题是此行为背后的原因是什么(我想这与继承使Bar进入A名称空间这一事实有关,但是我找不到任何文档来支持该理论。

3
C ++十进制类型和括号-为什么?
之前已经讨论 过该主题,但这不是重复的。 当有人询问decltype(a)和之间的区别时decltype((a)),通常的答案是- a是变量,(a)是表达式。我觉得这个答案不令人满意。 首先,a也是一个表达。主表达式的选项包括: (表情) id表达 更重要的是,decltype的措词非常非常明确地考虑了括号: For an expression e, the type denoted by decltype(e) is defined as follows: (1.1) if e is an unparenthesized id-expression naming a structured binding, ... (1.2) otherwise, if e is an unparenthesized id-expression naming a non-type template-parameter, ... (1.3) otherwise, if e …

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.