Questions tagged «c++»

C ++是一种通用编程语言。它最初被设计为C的扩展,并且具有类似的语法,但是现在它是一种完全不同的语言。使用此标记可解决有关将要使用C ++编译器编译的代码的问题。对于与特定标准修订版[C ++ 11],[C ++ 14],[C ++ 17]或[C ++ 20]等相关的问题,请使用特定于版本的标记。

2
如果未定义的C ++行为符合C定义的行为会发生什么?
我有一个*.cpp使用C ++编译的文件(不是C编译器)。包含函数依赖于强制转换(请参见最后一行),该强制转换似乎是在C中定义的(如果我错了,请更正!),但对于这种特殊类型,则不在C ++中定义。 [...] C++ code [...] struct sockaddr_in sa = {0}; int sockfd = ...; sa.sin_family = AF_INET; sa.sin_port = htons(port); bind(sockfd, (struct sockaddr *)&sa, sizeof sa); [...] C++ code [...] 由于我将其编译为C ++文件,因此这是现在定义的还是未定义的行为?还是我需要将其移动到*.c文件中以使其定义为行为?

2
调用伪析构函数以获取浮点常量的有效语法
考虑下面的演示程序。 #include <iostream> int main() { typedef float T; 0.f.T::~T(); } 该程序由编译Microsoft Visual Studio Community 2019。 但是clang并gcc发出这样的错误 prog.cc:7:5: error: unable to find numeric literal operator 'operator""f.T' 7 | 0.f.T::~T(); | ^~~~~ 如果要像这样写表达式,( 0.f ).T::~T()则所有三个编译器都将编译该程序。 因此出现一个问题:此记录在0.f.T::~T()语法上是否有效?如果没有,那么什么语法规则就被打破了?

3
如何避免从int(0)到向量指针的隐式转换
在某些情况下,我想收集JSON中键的路径的所有节点名称。考虑数组索引“ 0”,“ 1”的条件,也可以,但是很容易忘记引号,这在取消引用时会导致崩溃。所以我想拒绝这个。例: #include <vector> #include <iostream> int func(const std::vector<const char*>& pin) { return pin.size(); } int main() { // {"aname", "3", "path", "0"} wanted but this still compile std::cout << func({"aname", "3", "path", 0}) << std::endl; } 我发现并尝试过该如何避免在非构造函数上进行隐式转换?如下: #include <vector> #include <iostream> int func(const std::vector<const char*>& pin) { return …


2
使用空指针参数和不可能的后置条件构造标准异常
考虑以下程序: #include<stdexcept> #include<iostream> int main() { try { throw std::range_error(nullptr); } catch(const std::range_error&) { std::cout << "Caught!\n"; } } 使用libstdc ++调用的GCC和Clang std::terminate并通过消息中止程序 terminate called after throwing an instance of 'std::logic_error' what(): basic_string::_S_construct null not valid 用libc ++ segfaults构造异常的Clang。 见godbolt。 编译器的行为符合标准吗?标准[diagnostics.range.error](C ++ 17 N4659)的相关部分确实说std::range_error有const char*构造函数重载,应该优先于const std::string&重载。本节也没有说明构造函数的任何前提条件,而只说明了后置条件 后置条件:strcmp(what(), what_­arg) == 0。 如果what_arg为空指针,则此后置条件始终具有未定义的行为,那么这是否意味着我的程序也具有未定义的行为并且两个编译器的行为一致?如果没有,应该如何阅读标准中如此不可能的后置条件? …

2
我可以将临时管道返回到范围操作吗?
假设我有一个generate_my_range模拟a 的类range(尤其是is regular)。然后,以下代码正确: auto generate_my_range(int some_param) { auto my_transform_op = [](const auto& x){ return do_sth(x); }; return my_custom_rng_gen(some_param) | ranges::views::transform(my_transform_op); } auto cells = generate_my_range(10) | ranges::to<std::vector>; 是my_custom_rng_gen(some_param)由(第一个)管道运算符按值获取的,还是离开generate_my_range范围后是否有悬挂的引用? 函数调用会一样ranges::views::transform(my_custom_rng_gen(some_param),my_transform_op)吗? 如果我使用左值引用会正确吗?例如: auto generate_my_range(int some_param) { auto my_transform_op = [](const auto& x){ return do_sth(x); }; auto tmp_ref = my_custom_rng_gen(some_param); return tmp_ref | …
9 c++  range-v3 


2
有哪些名称空间,有哪些规则?
注意:这个问题是关于name space,不是namespace。 C ++标准引用了name space,但是我没有看到它的定义。该标准说标签和宏位于不同的名称空间中。所有其他引用name space都在C / C ++兼容性部分中,如下所示(当前草案): 这是C和C ++之间少数可归因于新的C ++名称空间定义的不兼容性之一,在新的C ++名称空间定义中,名称可以在单个作用域中声明为类型和非类型,从而导致非类型名称隐藏类型名称,并要求使用关键字class,struct,union或enum来引用类型名称。这个新的名称空间定义为C ++程序员提供了重要的符号方便,并有助于使用户定义类型的使用与基本类型的使用尽可能相似。 这个新的名称空间定义是什么?在标准中哪里可以找到它?确切的规则是什么?规则似乎比“非类型隐藏类型”更复杂。就像,这不会编译: typedef int Foo; // Foo is a type void Foo(); // not a type, but compile error, instead of hiding 但这确实是: struct Foo { }; // Foo is a type as well void Foo(); // …
9 c++  namespaces 

1
UB是否可以恢复其生存期已结束的对象的成员函数协程?
这个问题源于以下评论:C ++ 20协程的Lambda生命周期说明 关于这个例子: auto foo() -> folly::coro::Task<int> { auto task = []() -> folly::coro::Task<int> { co_return 1; }(); return task; } 所以问题是执行返回的协程是否foo会导致UB。 “调用”成员函数(在对象的生存期结束之后)是UB:http : //eel.is/c++draft/basic.life#6.2 ...可以使用任何表示对象将要或曾经位于的存储位置的地址的指针,但只能以有限的方式使用。[...]该程序在以下情况下具有未定义的行为: [...] -指针用于访问对象的非静态数据成员或调用该对象的非静态成员函数,或者 但是,在此示例中: ()Lambda的生存期仍然有效时,将调用Lambda 的运算符 然后将其挂起, 然后lambda被破坏, 然后成员函数(operator ())随后恢复。 是否将此恢复视为未定义的行为?

1
未指定的隐式对象创建
自从接受了P0593用于低级对象操作的对象隐式创建以来,现在可以在C ++ 20中隐式创建对象。 提案中特别引入的措辞允许某些操作(例如std::malloc)自动创建和启动某些类型的对象(称为隐式生命周期类型)的生存期,如果引入此类对象会导致具有其他未定义行为的程序具​​有定义的行为。参见[intro.object] / 10。 草案现在进一步指出,如果可以隐式创建多个这样的对象集以赋予程序定义的行为,则未指定创建这些对象集中的哪个。(有关的句子似乎没有出现在我可以访问的上一个提案修订版R5中,而是在提交草案中。) 实际上是否有一个程序可以针对这种隐式创建的对象集进行选择?换句话说,是否有一个程序通过此新规则具有已定义但未指定的行为,从而可以从输出中推断出创建了哪些隐式对象类型集(超过一个可能的类型)? 还是这句话只是为了阐明程序在抽象机上的执行(没有明显的影响)?

2
为什么C ++在对Foo <T> :: Foo(T &&)的调用中不能推断T?
给定以下模板结构: template&lt;typename T&gt; struct Foo { Foo(T&amp;&amp;) {} }; 这可以编译,并T推导为int: auto f = Foo(2); 但这无法编译:https : //godbolt.org/z/hAA9TE int x = 2; auto f = Foo(x); /* &lt;source&gt;:12:15: error: no viable constructor or deduction guide for deduction of template arguments of 'Foo' auto f = Foo(x); ^ &lt;source&gt;:7:5: note: candidate function …

2
C中的const限定词和C ++中的const限定词有什么区别?
我找到了用户R.的评论: C和C ++语言不同。特别地,C const与C ++无关const。 我知道,constC中的const限定符和C ++中的限定符之间的区别是其默认链接。 const在C ++中,在命名空间范围内使用限定符声明的对象具有内部链接,而在C中,const在全局范围内声明带有限定符的对象(static在之前没有限定符const)具有外部链接。 但是在C和C ++语言之间,它们又有何不同?我认为两种语言在概念和目的上都具有相同的含义。 我的问题: C中的const限定词和C ++中的const限定词有什么区别? “ const”在C和C ++中有何不同的答案?不要在限定词的上下文中指出C和C ++语言之间的确切差异const。只有您不能或只能使用某种语言来做。

2
复制具有线程安全规则建议的非const参数的构造函数?
我有一些旧代码的包装。 class A{ L* impl_; // the legacy object has to be in the heap, could be also unique_ptr A(A const&amp;) = delete; L* duplicate(){L* ret; legacy_duplicate(impl_, &amp;L); return ret;} ... // proper resource management here }; 在此旧版代码中,“复制”对象的函数不是线程安全的(调用相同的第一个参数时),因此const在包装器中未对其进行标记。我猜想遵循现代规则:https : //herbsutter.com/2013/01/01/video-you-dont-know-const-and-mutable/ 这duplicate看起来是实现复制构造函数的一种好方法,除了细节不是const。因此,我不能直接这样做: class A{ L* impl_; // the legacy object has …

2
C ++-为什么这里需要'template'关键字?
我有以下代码: template &lt;typename TC&gt; class C { struct S { template &lt;typename TS&gt; void fun() const {} }; void f(const S&amp; s) { s.fun&lt;int&gt;(); } }; // Dummy main function int main() { return 0; } 在同时使用gcc 9.2和clang(9.0)进行构建时,由于template调用关键字需要关键字,因此出现编译错误fun。lang声显示: error: use 'template' keyword to treat 'fun' as a dependent template name …

2
在程序员一级使用C ++ std :: atomic可以保证什么?
我已经听过并阅读了有关的几篇文章,演讲和stackoverflow问题std::atomic,并且我想确保自己已经很好地理解了。由于MESI(或派生的)高速缓存一致性协议,存储缓冲区,使队列无效等可能存在延迟,因此我仍然对高速缓存行的可见性感到困惑。 我读到x86具有更强的内存模型,并且如果缓存失效被延迟,x86可以还原启动的操作。但是我现在只对我作为独立于平台的C ++程序员应该承担的兴趣感兴趣。 [T1:线程1 T2:线程2 V1:共享原子变量] 我了解std :: atomic可以保证, (1)在变量上不发生数据争用(由于对缓存行的独占访问)。 (2)取决于我们使用哪种memory_order,它(在有障碍的情况下)保证发生顺序一致性(在障碍之前,之后或之后)。 (3)在T1上执行原子write(V1)之后,T2上的原子RMW(V1)将是连贯的(其缓存行将已用T1上的写入值进行更新)。 但是正如缓存一致性入门所述, 所有这些事情的含义是,默认情况下,加载可以获取过时的数据(如果相应的失效请求位于失效队列中) 那么,以下正确吗? (4)std::atomic不保证T2在T1上执行原子write(V)之后不会读取原子read(V)上的“陈旧”值。 问题(4)是否正确:如果无论延迟如何,在T1上进行原子写入都会使高速缓存行无效,那么当原子RMW操作而不是在原子读取上进行操作时,T2为什么要等待无效生效? 问题(4)是否错误:线程何时可以在执行过程中读取“过时”值并且“可见”? 非常感谢您的回答 更新1 所以看来我在(3)上错了。想象以下交织,初始V1 = 0: T1: W(1) T2: R(0) M(++) W(1) 即使在这种情况下,保证T2的RMW完全在W(1)之后发生,它仍然可以读取“过时的”值(我错了)。据此,atomic不能保证完全的缓存一致性,而只能保证顺序一致性。 更新2 (5)现在想象这个例子(x = y = 0并且是原子的): T1: x = 1; T2: y = 1; T3: if (x==1 &amp;&amp; y==0) print("msg"); …

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.