小编Dan*_*ica的帖子

C++中的标准或自定义异常?

对于库中的代码,是更好的做法是创建和抛出自定义异常类(库::例外),或只是抛出标准异常(runtime_error,invalid_argument等)?

c++ standards exception

19
推荐指数
2
解决办法
7140
查看次数

为什么 std::array<T,0> 根据 libc++ 中的 T 调整大小和对齐?

在 libc++ 中, 的特化std::array<T,0>有一个成员 ( const)char数组,该数组根据T(源) 进行对齐和调整大小。我想知道这个实现的原因是什么,因为这个成员(__elems_)似乎没有在任何地方使用。为了进行比较,libstdc++使用空成员,而Microsoft STL如果不可默认构造则使用空成员T(否则,它会创建单元素数组)。

差异的现场演示:https ://godbolt.org/z/1o167na6z

c++ libc++ stdarray

16
推荐指数
1
解决办法
387
查看次数

是否可以将容器的复制构造函数定义为已删除的非可复制值类型?

如果我们有一个具有不可复制值类型的容器,这样的容器类仍然定义了复制构造函数,只是它可能不会被调用.

using T = std::vector<std::unique_ptr<int>>;
std::cout << std::is_copy_constructible_v<T>; // prints out "1" (libstdc++)
Run Code Online (Sandbox Code Playgroud)

这可能会导致"隐藏"问题,例如此处讨论的问题:Visual Studio 2017是否需要显式移动构造函数声明?.

我的问题是标准库实现是否可以将此类复制构造函数定义为有条件删除,即在不可复制的值类型的情况下删除.这对我来说是完全合理的(至少在有C++概念之前).这种实施是否符合标准?

c++ containers copy-constructor noncopyable language-lawyer

13
推荐指数
1
解决办法
597
查看次数

C ++ 20是否为“溢出”的有符号整数很好地定义了左移?

在当前的C ++标准草案中,左移位运算符的定义如下[expr.shift]:

的值E1 << E2是唯一的值一致来E1×2^E2模2^N,其中N是结果的类型的宽度。

考虑int E1 = 2^31-1 = 2'147'483'647,E2 = 1并且int具有32位。再有就是数的无限数量一致,以 E1×2^E2 = 4'294'967'294模2^N = 2^32,即,所有的数字4'294'967'294 + k×2^32,其中k的任意整数。示例是4'294'967'294(k=0)或-2(k=-1)。

我不明白这些数字中的唯一值表示标准的含义。这是否意味着可以由结果数据类型表示的唯一值?然后,我假设结果定义为-2。这种解释正确吗?

在C ++ 20之前,定义是不同的,这种情况将导致未定义的行为。我想这个变化与负号整数的强制性2's补码表示有关。

实际上,现在不再E1需要非负数。因此,似乎将-1 << 1其定义为-2。那也对吗?

c++ bit-shift language-lawyer c++20

11
推荐指数
1
解决办法
501
查看次数

std :: make_array的当前状态

这里std::make_array提出的功能的当前状态是什么?我找不到有关其潜在接受度的任何信息.根据cppreference.com,它位于命名空间中.在C++编译器支持和Wikipedia-C++ 17,Wikipedia-C++ 20和C++ 17标准草案中都没有提到它.std::experimental

c++ arrays

10
推荐指数
3
解决办法
1731
查看次数

clang++-12 找不到库范围

我正在测试 C++ 20 的范围,这是我的main.cpp:

#include <ranges>
#include <iostream>

int main()
{
    auto const ints = {0,1,2,3,4,5};
    auto even = [](int i) { return 0 == i % 2; };
    auto square = [](int i) { return i * i; };

    for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
        std::cout << i << ' ';
    }

    std::cout << '\n';
}

Run Code Online (Sandbox Code Playgroud)

编译它clang++-12但找不到“范围”:

$ clang++-12 --version
Ubuntu clang version 12.0.1-++20210525082622+328a6ec95532-1~exp1~20210525063352.95
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin …
Run Code Online (Sandbox Code Playgroud)

c++ clang c++20 std-ranges

10
推荐指数
0
解决办法
5599
查看次数

为什么 std::allocator&lt;T&gt;::allocate 调用 ::operator new?

成员函数的文档std::allocator<T>::allocate在 ( [allocator.members] ) 中说:

\n
\n

备注:数组的存储是通过调用 \xe2\x80\x8b::\xe2\x80\x8boperator new ([new.delete]) 获得的,但未指定该函数的调用时间和频率。该函数启动数组对象的生命周期,但不启动任何数组元素的生命周期。

\n
\n

我想知道为什么它说::operator new而不只是operator new?双冒号有什么区别吗?operator new如果省略了双冒号,这里可以调用哪个其他的?

\n

c++ new-operator allocator language-lawyer

10
推荐指数
1
解决办法
475
查看次数

结构化绑定在C++ 17中引入的标识符类型有哪些?

据我所知,C++ 17中结构化绑定引入的标识符实际上是对某些"隐藏"变量的引用.这样

auto [ a, b ] = std::make_tuple(1, 2);
Run Code Online (Sandbox Code Playgroud)

是一种等同于

auto e = std::make_tuple(1, 2);
auto& a = std::get<0>(e);
auto& b = std::get<1>(e);
Run Code Online (Sandbox Code Playgroud)

但是,如果我打印出来std::is_reference<decltype(a)>::value,我会0在1第二种情况下进入第一种情况.这是为什么?

c++ reference decltype c++17 structured-bindings

9
推荐指数
1
解决办法
409
查看次数

从std :: string中不必要地清空move-from

std::string即使原始存储的字符串很短并且应用了短字符串优化,libstdc ++和libc ++也会使对象变为空.在我看来,这种清空会产生额外的和不必要的运行时开销.例如,这是std::basic_stringlibstdc ++ 的移动构造函数:

basic_string(basic_string&& __str) noexcept
  : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator())) {
    if (__str._M_is_local()) 
      traits_type::copy(_M_local_buf, __str._M_local_buf, _S_local_capacity + 1);
    else {
      _M_data(__str._M_data());
      _M_capacity(__str._M_allocated_capacity);
    }
    _M_length(__str.length());
    __str._M_data(__str._M_local_data());  // (1)
    __str._M_set_length(0);                // (2)
  }
Run Code Online (Sandbox Code Playgroud)

(1)是一个在短字符串情况下无效的赋值,因为数据已经设置为本地数据,所以我们只需为指针指定与之前分配的值相同的值.

(2)清空字符串设置字符串大小并重置本地缓冲区中的第一个字符,据我所知,标准不要求.

通常,库实现者尝试尽可能高效地实现标准(例如,删除的内存区域不会被清零).我的问题是,如果可能有任何特殊原因导致移动的字符串被清空,即使它不是必需的,也会增加不必要的开销.其中,可以很容易地消除,例如:

basic_string(basic_string&& __str) noexcept
  : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator())) {
    if (__str._M_is_local()) {
      traits_type::copy(_M_local_buf, __str._M_local_buf, _S_local_capacity + 1);
      _M_length(__str.length());
    }
    else {
      _M_data(__str._M_data());
      _M_capacity(__str._M_allocated_capacity);
      _M_length(__str.length());
      __str._M_data(__str._M_local_data());  // (1)
      __str._M_set_length(0);                // (2)
    }
  }
Run Code Online (Sandbox Code Playgroud)

c++ string libstdc++ move-semantics

9
推荐指数
1
解决办法
275
查看次数

为什么没有std :: uninitialized_move_if_noexcept?

C++ 17补充说std::uninitialized_move,但没有内部std::uninitialized_move_if_noexcept使用std::move_if_noexcept.在我看来,这将是有用的,因为现在,如果我们想要重新分配,我们仍然需要写一些东西

if constexpr (!std::is_nothrow_move_constructible_v<value_type>
              && std::is_copy_constructible_v<value_type>)
  std::uninitialized_copy(...);
else 
  std::uninitialized_move(...); 
Run Code Online (Sandbox Code Playgroud)

有没有特别的原因为什么std::uninitialized_move_if_noexcept没有在C++ 17中引入?

c++ move placement-new noexcept c++17

9
推荐指数
1
解决办法
236
查看次数