在C++ 11中,我们获得了用户定义的文字.C++标准有这些例子,例如:
long double operator "" _w(long double);
Run Code Online (Sandbox Code Playgroud)
它说文字应该以下划线开头:
17.6.4.3.5用户定义的文字文字
不以下划线开头的文字符号标识符保留用于将来的标准化.
但是,标准中还有另一部分说
17.6.4.3.2全局名称
某些名称和函数签名集始终保留给实现:
- 每个包含双下划线_ _的名称或以下划线后跟大写字母(2.12)开头的名称保留给实现任何用途.
- 以下划线开头的每个名称都保留给实现,以用作全局名称空间中的名称.
我希望更好地理解17.6.4.3.2(全局名称)所说的/意味着什么以及它与17.6.4.3.5(用户定义的字面文字)的关系.特别:
_w在命名空间中定义用户定义的文字(如上所述)(即不在全局命名空间中)?如果是这样,我希望标准能说明这一点._W(大写)__w和_w__(两个连续的下划线).正确?编辑:
作为后续行动,标准的一部分说:
13.5.8用户定义的文字
[...]
2 声明者id为文字操作符id的声明应该是命名空间范围函数或函数模板的声明(它可以是友元函数(11.3)),函数模板的显式实例化或特化,或者使用声明(7.3.3).使用literal-operator-id声明的函数是文字运算符.使用literal-operator-id声明的函数模板是文字运算符模板.
强调我的.当它说"namespace-scope"时,这意味着用户定义的文字需要在用户定义的命名空间中声明(即不在全局命名空间中)?
稍后编辑:
当问题第一次被问到时它不存在,但现在也有这个相关的问题和答案,读者可以在审查下面的答案后另外检查.
请考虑以下示例.目标是使用两个线程,一个用于"计算"一个值,另一个用于消耗和使用计算值(我试图简化这个).计算线程通过使用条件变量向另一个线程发信号通知该值已经计算并准备就绪,之后等待线程消耗该值.
// Hopefully this is free from errors, if not, please point them out so I can fix
// them and we can focus on the main question
#include <pthread.h>
#include <stdio.h>
// The data passed to each thread. These could just be global variables.
typedef struct ThreadData
{
pthread_mutex_t mutex;
pthread_cond_t cond;
int spaceHit;
} ThreadData;
// The "computing" thread... just asks you to press space and checks if you did or not
void* getValue(void* td)
{
ThreadData* data …Run Code Online (Sandbox Code Playgroud) 可能重复:
分配给较大宽度的整数时的C整数溢出行为
我在google搜索中没有找到明确的答案.假设你有两个表达式:
int16_t a16 = 100;
int16_t b16 = 2000;
int16_t result16 = (a16 * b16) / a16;
int8_t a8 = 100;
int8_t b8 = 20;
int8_t result8 = (a8* b8) / a8;
Run Code Online (Sandbox Code Playgroud)
当评估表达式(a16 * b16) / a16和(a8 * b8) / a8,是他们总是晋升int评价中,然后最终结果被转换回所需的类型(int16_t或int8_t)就在分配之前,或者是这个整数的推广完全可选的?在评估整数表达式时总是进行整数提升,还是只是简单地允许?
如果它总是完成,那么我可以预期这两个操作不会溢出(假设int是32位).如果只允许(并且不需要),则操作可能会溢出.我想更好地了解这种行为.
这个问题是很大的,因为它对之间有什么区别答案rvalue,lvalue,xvalue,glvalue,和prvalue.最佳答案对每个答案都有不错的解释,当我阅读它们时,我理解它们之间的差异.但是,我很难将它们直接放在脑海中,每当有人使用这些术语来提醒自己哪一个是哪个时,我都必须谷歌.
是否有任何常见的助记符或其他方式让人记住哪一个是哪个?我真的希望能够将它们全部直接放在我的脑海中,而不是像现在这样将它们混合在一起.
我有一个struct包含数组,我想将初始化列表传递给struct的构造函数以转发到数组.为了说明,我试过:
#include <initializer_list>
struct Vector
{
float v[3];
Vector(std::initializer_list<float> values) : v{values} {}
};
int main()
{
Vector v = {1, 2, 3};
}
Run Code Online (Sandbox Code Playgroud)
error: cannot convert ‘std::initializer_list<float>’ to ‘float’ in initialization
我尝试使用括号而不是大括号,v但这给出了错误:
error: incompatible types in assignment of ‘std::initializer_list<float>’ to ‘float [3]’
尝试这样做的主要动机是避免clang生成的以下警告:
template <int N>
struct Vector
{
float v[N];
};
template <>
struct Vector<2>
{
float x, y;
};
int main()
{
Vector<2> v2 = {1.0f, 2.0f}; // Yay, works …Run Code Online (Sandbox Code Playgroud) 在阅读了关于这个问题的许多评论之后,有几个人(这里和这里)建议这段代码:
int val = 5;
int r = (0 < val) - (val < 0); // this line here
Run Code Online (Sandbox Code Playgroud)
会引起分支.不幸的是,他们都没有给出任何理由或者说它为什么会导致分支(三角形暗示它需要类似cmove指令或预测,但并不真正说明原因).
这些人是否正确"表达中使用的比较不会产生分支"实际上是神话而不是事实?(假设你没有使用一些深奥的处理器)如果是这样,你能举个例子吗?
我以为不会有任何分支(假设没有逻辑"短路"),现在我很好奇.
这不是一个惯用的MVCE,但它应该说明这个问题.给出以下代码:
fn foo() -> Result<String, i32> {
return Ok("world".to_string());
}
fn bar() -> Result<String, i32> {
let mut value = String::new();
value.push_str(&try!(foo())); // this line here
return Ok("Hello ".to_string() + &value);
}
fn main() {
match bar() {
Ok(message) => println!("{}", message),
_ => return,
}
}
Run Code Online (Sandbox Code Playgroud)
Rust返回错误:
<std macros>:3:43: 3:46错误:不匹配的类型:
预期str,
找到collections::string::String
(预期str,
找到结构collections::string::String)[E0308]
<std macros>:3 $ crate:: result:: Result:: Ok ( val ) => val , $ crate:: result:: Result:: …
可能重复:
复制和直接初始化的动机背后的动机是什么?
通过复制初始化,我的意思是这样的:
struct MyStruct
{
MyStruct(int) {}
MyStruct(const MyStruct&) {}
};
MyStruct s = 5; // needs *both* the int and copy constructor
Run Code Online (Sandbox Code Playgroud)
尽管用C++编程多年,但我从未意识到上面的代码需要复制构造函数(感谢jogojapan).暂时一直被遗忘,因此我甚至都不知道它是否存在(至少在肤浅的层面,尽管它被优化了),直到它被指出给我.
经过大量的谷歌搜索,我了解它是如何工作的.我的问题是为什么它是这样的?
为什么标准不能使上面的例子不需要复制构造函数?是否有一些特定的案例/示例表明在这种初始化中需要复制构造函数很重要?
如果没有合理的解释为什么事情就是他们的方式,我只是把它看作是一件讨厌的神器,但如果有一些重要的东西我不想知道,我宁可不要无知.
注意:当我说正则表达式时,[\0]我指的是正则表达式[\0](不包含在C风格的字符串中,然后就是这样"[\\0]").如果我没有在它周围加上引号,那么它不是C风格的字符串,反斜杠不应该被解释为转义为C风格的字符串.
受到这个问题和我的调查的启发,我在clang 3.4中尝试了以下代码:
#include <regex>
#include <string>
int main()
{
std::string input = "foobar";
std::regex regex("[^\\0]*"); // Note, this is "\\0", not "\0"!
return std::regex_match(input, regex);
}
Run Code Online (Sandbox Code Playgroud)
显然,clang并不喜欢这样,因为它抛出:
std::__1::regex_error:表达式包含无效的转义字符或尾随转义.
它似乎是[^\0]部分(改变它[^\n]或类似的东西工作正常).它似乎是一个无效的转义字符.我想澄清一点,我不是在讨论'\0'字符(空字符)或'\n'字符(换行符).在C风格的字符串中,我所说的是"\\0"(包含反斜杠零的字符串)和"\\n"(包含反斜杠n的字符串)."\\n"似乎"\n"被正则表达式引擎转化为了它,但它扼杀了"\\0".
C++ 11标准在第28.13节[re.grammar]中说:
由
basic_regexECMMAcript标志构造的对象识别的正则表达式语法是由ECMA-262指定的,除非如下所述.
我不是ECMA-262的专家,但是我在JSFiddle上尝试了正则表达式,它在JavaScript领域工作得很好.
所以现在我想知道正则表达式[^\0]是否在ECMA-262中有效并且C++ 11标准删除了对它的支持(在后面的内容中... except as specified below.).
问题 …
贾斯汀对另一个问题的回答使得我觉得非常有趣,但无法解释.请考虑以下代码:
std::vector<std::string> v;
v.push_back("Hello, world!"); // Doesn't call strlen.
v.emplace_back("Hello, world!"); // Calls strlen.
Run Code Online (Sandbox Code Playgroud)
如果查看程序集,则emplace_back生成一个调用strlen,而push_back不是(在gcc 8.1和clang 6.0中使用测试-Ofast).
为什么会这样?为什么不能emplace_back在strlen这里优化呼叫?我最初的想法是在函数调用之前push_back隐式创建(因此构造函数直接传递字符串文字,这是最佳处理),而在函数调用之后创建(因此构造函数转发字符串文字,我推测已经从a衰减到a ,因此需要打电话).std::string std::stringemplace_backstd::string std::stringconst char [N]const char *strlen
但是emplace_back需要一个T&&参数,和我的测试显示,字符串文字不应该在这里腐烂的指针.显然,我忽略了一些东西.