Questions tagged «c++»

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

2
程序永远不会终止有效的C ++程序吗?
是否需要终止程序?换句话说,是一个在技术上永远无法运行的程序吗?请注意,这与空循环无关。谈论永远做“东西”(即可观察到的行为)的程序。 例如这样的事情: int main() { while (true) { try { get_input(); // calls IO process(); put_output(); // calls IO, has observable behavior // never break, exit, terminate, etc } catch(...) { // ignore all exceptions // don't (re)throw // never go out of loop } } } 这更多是一个学术问题,因为根据经验,所有理智的编译器都会为上述程序生成预期的代码(当然,假设没有其他UB来源)。是的,当然,有很多程序永远都不会终止(操作系统,嵌入式服务器)。但是有时标准是古怪的,因此是个问题。 切线:“算法”的许多(某些)定义要求算法必须终止,即,一系列永不终止的运算不被视为算法。 相切的。暂停问题指出,无法存在一种算法来确定任意程序是否针对输入完成。但是,对于该特定程序,由于没有导致退出main的分支,因此编译器可以轻松确定该程序永远不会结束。但是,这是无关紧要的,因为问题是语言律师。

2
为什么C ++ 20之前std :: swap没有标记为constexpr?
在C ++ 20中,std::swap成为一个constexpr函数。 我知道标准库在标记事物方面确实落后于该语言constexpr,但是到了2017年,<algorithm>它和许多其他事物一样已经成为constexpr了。但是- std::swap不是。我隐约记得有一些奇怪的语言缺陷阻止了这种标记,但是我忘记了细节。 有人可以简洁明了地解释吗? 动机:需要理解为什么在C ++ 11 / C ++ 14代码中标记std::swap()类似函数的想法可能不是一个好主意constexpr。

3
具有非常量指针和相同地址的const参数的指针的函数调用
我想编写一个函数,该函数输入一个数据数组并使用指针输出另一个数据数组。 我想知道如果两者都指向同一地址会产生什么结果src,dst因为我知道编译器可以针对const进行优化。它是未定义的行为吗?(我同时标记了C和C ++,因为我不确定答案是否可能会有所不同,并且我想了解两者。) void f(const char *src, char *dst) { dst[2] = src[0]; dst[1] = src[1]; dst[0] = src[2]; } int main() { char s[] = "123"; f(s,s); printf("%s\n", s); return 0; } 除了上述问题,如果删除const原始代码中的,是否定义明确?

2
std :: chrono :: years的存储空间真的至少是17位吗?
来自cppreference std::chrono::years (since C++20) duration</*signed integer type of at least 17 bits*/, std::ratio<31556952>> 使用libc++,它似乎的强调存储std::chrono::years就是short其中签订16位。 std::chrono::years( 30797 ) // yields 32767/01/01 std::chrono::years( 30797 ) + 365d // yields -32768/01/01 apparently UB cppreference上有错别字吗? 例: #include <fmt/format.h> #include <chrono> template <> struct fmt::formatter<std::chrono::year_month_day> { char presentation = 'F'; constexpr auto parse(format_parse_context& ctx) { …
14 c++  chrono  c++20  libc++ 

3
在两个范围内以降序对向量排序
假设我有一个整数向量: std::vector<int> indices; for (int i=0; i<15; i++) indices.push_back(i); 然后我按降序对其进行排序: sort(indices.begin(), indices.end(), [](int first, int second) -> bool{return indices[first] > indices[second];}) for (int i=0; i<15; i++) printf("%i\n", indices[i]); 这将产生以下结果: 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 现在,我想将数字3、4、5和6移到末尾,并保持它们的降序(最好不必sort第二次使用)。即,这就是我想要的: 14 13 12 11 10 …

1
Clang不编译代码,但是gcc和msvc编译了它
我不明白这是什么问题:在我的代码中还是在编译器中(不太可能)。有一段这样的代码: #include <iostream> #include <type_traits> #include <set> template<typename T, typename = void> struct TestA: std::false_type {}; template<typename T> struct TestA<T, std::void_t<typename T::reverse_iterator>> : std::true_type {}; template<typename T> struct TestA<T, std::void_t<typename T::dummy_iterator>> : std::true_type {}; int main() { std::cout << TestA<std::set<int>>::value; } GCC和MSVC都可以对其进行编译。我使用不同版本的GCC和MSVC 17(本地)和19在Godbolt上进行了测试。这是一个链接:https ://godbolt.org/z/Enfm6L 。 但是Clang不会编译它并发出错误: redefinition of `'TestA<T, std::void_t<typename …

2
向量作为键在C ++内部如何工作?
该SO回答说,带有向量作为密钥的STL映射,该向量可用作密钥。因此,当我们使用向量作为键时。由于键需要唯一,因此该键实际如何工作,因此当我们插入具有相同元素的另一个向量时,将map检查逐个元素重复还是向量名称确实指定了某些东西?就像数组的名称代表基地址一样。因此,可以将数组用作键,因为在这种情况下基地址可以用作键,但是在向量的情况下,键是什么。它是如何在内部工作的。 因为当我打印矢量的名称时,我确实得到了一个错误 vector<int> v; cout<<v; //error
14 c++  arrays  dictionary  vector  stl 

1
为什么GCC不能假设std :: vector :: size在此循环中不会改变?
我要求一个if (i < input.size() - 1) print(0);在此循环中得到优化的同事,这样input.size()就不会在每次迭代中都读取它,但事实证明并非如此! void print(int x) { std::cout << x << std::endl; } void print_list(const std::vector<int>& input) { int i = 0; for (size_t i = 0; i < input.size(); i++) { print(input[i]); if (i < input.size() - 1) print(0); } } 根据带有gcc选项的Compiler Explorer,-O3 -fno-exceptions我们实际上是在读取input.size()每个迭代并lea用于执行减法运算! movq …
14 c++  gcc  assembly 

1
我可以通过元素的完美转发来列表初始化std :: vector吗?
我注意到std :: vector的聚合 列表初始化在以下情况下执行复制初始化移动更适用。同时,多个emplace_backs可以满足我的需求。 我只能提出编写模板函数的不完善解决方案init_emplace_vector。但是,它仅对非显式单值构造函数最佳。 template <typename T, typename... Args> std::vector<T> init_emplace_vector(Args&&... args) { std::vector<T> vec; vec.reserve(sizeof...(Args)); // by suggestion from user: eerorika (vec.emplace_back(std::forward<Args>(args)), ...); // C++17 return vec; } 题 我真的需要使用emplace_back来尽可能高效地初始化std :: vector吗? // an integer passed to large is actually the size of the resource std::vector<large> v_init { …

1
为什么在不使用堆栈内存时分配堆栈内存?
考虑以下示例: struct vector { int size() const; bool empty() const; }; bool vector::empty() const { return size() == 0; } 生成的汇编代码vector::empty(通过clang,带有优化): push rax call vector::size() const test eax, eax sete al pop rcx ret 为什么要分配堆栈空间?完全不使用。该push和pop可以省略。优化的MSVC和gcc构建也为此功能使用了堆栈空间(请参阅godbolt),因此必须有一个原因。

1
当空基类也是成员变量时,为什么禁止空基优化?
空基优化非常棒。但是,它具有以下限制: 如果空基类之一也是第一个非静态数据成员的类型或类型的基,则禁止空基优化,因为相同类型的两个基子对象需要在对象表示中具有不同的地址最派生的类型。 要解释此限制,请考虑以下代码。该static_assert会失败。而将Foo或更改为或Bar从继承Base2将避免错误: #include <cstddef> struct Base {}; struct Base2 {}; struct Foo : Base {}; struct Bar : Base { Foo foo; }; static_assert(offsetof(Bar,foo)==0,"Error!"); 我完全了解这种行为。我不明白的是为什么存在这种特殊行为。显然添加它是有原因的,因为它是显式添加,而不是疏忽。这样做的理由是什么? 特别是为什么要要求两个基本子对象具有不同的地址?在上面,Bar是一个类型,并且foo是该类型的成员变量。我看不出为什么基类对Bar类型为的基类很重要foo,反之亦然。 确实,如果有的话,我希望它&foo与Bar包含它的实例的地址相同,因为在其他情况下它是必需的(1)。毕竟,我对virtual继承没有任何幻想,无论如何基类都是空的,并且带有的编译Base2显示在这种特殊情况下没有任何中断。 但是显然,这种推理在某种程度上是不正确的,并且在其他情况下,也需要这种限制。 假设答案应该针对C ++ 11或更高版本(我目前正在使用C ++ 17)。 (1)注意:EBO在C ++ 11中进行了升级,并且特别成为StandardLayoutTypes的必需项(尽管Bar,上面不是StandardLayoutType)。

1
__func__指针的两个constexpr实例的区别是否仍然是constexpr?
这是有效的C ++吗? int main() { constexpr auto sz = __func__ - __func__; return sz; } GCC和MSVC认为可以,而Clang认为不可以:Compiler Explorer。 所有编译器都同意这是可以的:Compiler Explorer。 int main() { constexpr auto p = __func__; constexpr auto p2 = p; constexpr auto sz = p2 - p; return sz; } Clang再次不喜欢这个,但是其他的都可以:Compiler Explorer int main() { constexpr auto p …

2
抛出和捕捉整数如何工作?
使用此代码: int main() { try { throw -1; } catch (int& x) { std::cerr << "We caught an int exception with value: " << x << std::endl; } std::cout << "Continuing on our merry way." << std::endl; return 0; } 我们有: /tmp$ ./prorgam.out Continuing on our merry way We caught …

1
如果constexpr-为什么要完全检查废弃的语句?
我在GCC 10中搞乱了c ++ 20 consteval并编写了这段代码 #include <optional> #include <tuple> #include <iostream> template <std::size_t N, typename Predicate, typename Tuple> consteval std::optional<std::size_t> find_if_impl(Predicate&& pred, Tuple&& t) noexcept { constexpr std::size_t I = std::tuple_size_v<std::decay_t<decltype(t)>> - N; if constexpr (N == 0u) { return std::nullopt; } else { return pred(std::get<I>(t)) ? std::make_optional(I) : find_if_impl<N …

1
这是std :: gcd中的错误吗?
我遇到了这种std::gcd意外的行为: #include <iostream> #include <numeric> int main() { int a = -120; unsigned b = 10; //both a and b are representable in type C using C = std::common_type<decltype(a), decltype(b)>::type; C ca = std::abs(a); C cb = b; std::cout << a << ' ' << ca << '\n'; std::cout << …

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.