小编Lyb*_*rta的帖子

char*和std :: uint8_t之间的reinterpret_cast* - 安全吗?

现在我们有时必须使用二进制数据.在C++中,我们使用字节序列,因为开头char是我们的构建块.定义为sizeof1,它是字节.char默认情况下,所有库I/O函数都使用.一切都很好,但总是有一点担心,有点奇怪,一些人的错误 - 一个字节中的位数是实现定义的.

所以在C99中,决定引入几个typedef让开发人员轻松表达自己的固定宽度整数类型.当然可选,因为我们从不想伤害便携性.其中uint8_t,迁移到C++ 11中std::uint8_t,固定宽度的8位无符号整数类型,对于真正想要使用8位字节的人来说是完美的选择.

因此,开发人员接受了新工具并开始构建库,这些库明确表示它们接受8位字节序列std::uint8_t*,std::vector<std::uint8_t>或者其他方式.

但是,或许经过深思熟虑,标准化委员会决定不要求实施,std::char_traits<std::uint8_t>因此禁止开发人员轻松,便携地实例化,比如说,std::basic_fstream<std::uint8_t>并轻松读取std::uint8_t二进制数据.或许,我们中的一些人不关心字节中的位数并且对它感到满意.

但遗憾的是,两个世界相互冲突,有时您必须将数据作为char*并将其传递给期望的库std::uint8_t*.但是等等,你说,是不是char变量位并std::uint8_t固定为8?它会导致数据丢失吗?

嗯,这里有一个有趣的标准.的char定义为保持正好一个字节和字节是内存的最低可寻址的块,所以用比特宽度比的较小不能有一个类型char.接下来,它被定义为能够保存UTF-8代码单元.这给了我们最小--8位.所以现在我们有一个typedef,它要求是8位宽,并且是一个至少8位宽的类型.但有其他选择吗?是的,unsigned char.请记住,签名char是实现定义的.还有其他任何一种 谢天谢地,没有.所有其他整数类型都需要超出8位的范围.

最后,std::uint8_t是可选的,这意味着如果未定义使用此类型的库将无法编译.但如果它编译呢?我可以非常自信地说,这意味着我们在8位字节的平台上CHAR_BIT == 8.

一旦我们有这方面的知识,我们已经8位字节,这std::uint8_t是实现为char或者unsigned char,我们可以假设,我们可以做reinterpret_castchar*std::uint8_t*,反之亦然?它是便携式的吗?

这是我的Standardese阅读技巧让我失望的地方.我读了关于安全派生的指针([basic.stc.dynamic.safety]),据我所知,以下内容:

std::uint8_t* buffer = /* ... */ ;
char* buffer2 …
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing language-lawyer c++11 uint8t

58
推荐指数
2
解决办法
1万
查看次数

传递值与const&和&&重载

因此,在查找移动语义之后,我发现当您打算转移所有权时,普遍的共识是通过值传递.但在Scott Meyer关于Universal引用的讨论中,我注意到std::vector::push_back有2个重载:

void push_back( const T& value );
void push_back( T&& value );
Run Code Online (Sandbox Code Playgroud)

所以我心想,void push_back( T value );不够吗?我问了一些最终导致以下测试用例的人:

#include <memory>
#include <iostream>
#include <type_traits>

struct A
{
    A() { std::cout << "A Default constructor\n"; }
    A(const A &) { std::cout << "A Copy\n"; }
    A(A &&) { std::cout << "A Move\n"; }
};

std::aligned_storage<sizeof(A)> contents;
A& alias = *reinterpret_cast<A*>(&contents);

void ByVal(A a)
{
    new (&contents) A(std::move(a));
    alias.~A();
}

void ByLCRef(A const& a)
{
    new …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue-reference move-semantics c++11

37
推荐指数
3
解决办法
5199
查看次数

为什么Allocator :: reference被逐步淘汰?

所以我在查看规范std::vector并注意到referencetypedef从Allocator::referenceC++ 03变为value_type&C++ 11.我很惊讶,所以我开始深入了解.

在C++03§20.1.5[lib.allocator.requirements]中,表32 X::reference定义为T&并且X::const_reference被定义为T const&.

然而,在C++ 11§17.6.3.5[allocator.requirements]有表28中,referenceconst_reference缺失.

接下来我们std::allocator_traits在C++ 11中添加了§20.6.8 ,但不包括reference.但§20.6.9 std::allocator确实如此.

最后,有§23.2.1[container.requirements.general]定义X::reference为"左值T"并且X::const_reference是"const左值T".

所以,我用Google搜索,发现这个文件(1,2)该提议移除reference从分配器的要求,但它并没有提到它后面的任何理由.但也有一个LWG问题反对这一变化.

此外,我找到了亚历山大·斯捷潘诺夫的访谈,其中他谈到了如何reference封装机器特定的内存布局和Herb Sutter的帖子,其中他谈到了指向容器元素,容器要求以及如何std::vector<bool>不是容器的指针.

那么,你怎么看待这一切呢?是reference有用的,做到了服务于它的目的是什么?"花式"引用如何符合标准?这是一个大胆的举措,以完全消除它们,制定更严格的容器要求并弃用std::vector<bool>

c++ memory-management allocator c++11

26
推荐指数
3
解决办法
592
查看次数

在std :: u8string和std :: string之间转换

添加了C ++ 20 char8_tstd::u8string用于UTF-8。但是,没有UTF-8版本,std::cout并且OS API通常期望char和执行字符集。因此,我们仍然需要一种在UTF-8和执行字符集之间进行转换的方法。

我重读了char8_t论文,看来在UTF-8和ECS之间转换的唯一方法是使用std::c8rtombstd::mbrtoc8函数。但是,它们的API极为混乱。有人可以提供示例代码吗?

c++ unicode utf-8 c++20

13
推荐指数
3
解决办法
545
查看次数

部分专业化和友谊

假设你有这样的A类:

template <typename T, typename U>
class A;
Run Code Online (Sandbox Code Playgroud)

和B级这样:

template <typename T>
class B;
Run Code Online (Sandbox Code Playgroud)

现在你想要两个班级成为朋友,当T是同一类型时,这可能吗?

所以例如A<int, long>是朋友,B<int>B<int>朋友在A<int, U>哪里U可以是任何类型.

c++ templates friend partial-specialization

9
推荐指数
0
解决办法
231
查看次数

使用概念禁用类专门化

我正在std::span使用Concepts TS 实现我自己的版本.我无法实现这些构造函数:

template<class Container> constexpr span(Container& cont);
template<class Container> constexpr span(const Container& cont);
Run Code Online (Sandbox Code Playgroud)

备注:这些构造函数不应参与重载决策,除非:

  • Container不是专业化的span,而且
  • Container 不是专业化的 array

如何使用概念实现这一点?

c++ c++-concepts c++20

8
推荐指数
1
解决办法
170
查看次数

为什么std :: span缺少size_type?

我一直在更新使用homebrew span类的旧代码,使之更符合C ++ 20的要求,std::span并且由于std::span没有size_type和有,我遇到了编译错误index_type。关于是否index_type应该签名已经发生了巨大的变化,但是为什么要跳过size_type呢?这会破坏期望容器(或类似容器的对象)具有的通用代码size_type

c++ c++20 std-span

8
推荐指数
2
解决办法
549
查看次数

直接写入std :: string的char*buffer

所以我有一个std::string并且有一个函数可以接受char*并写入它.既然std::string::c_str()std::string::data()回来了const char*,我不能用它们.所以我分配了一个临时缓冲区,用它调用一个函数并将其复制到std::string.

现在我计划处理大量信息,复制这个缓冲区会产生明显的影响,我想避免它.

有人建议使用&str.front()&str[0]但是它会调用未定义的行为吗?

c++ string language-lawyer c++14 c++17

7
推荐指数
1
解决办法
4664
查看次数

使用概念启用类模板的成员函数

所以我有一个概念Fooable:

template <typename T>
concept bool Fooable()
{
    return requires(...){ ... };
}
Run Code Online (Sandbox Code Playgroud)

我有一个类模板Bar,它将类型T作为模板参数,我想只在以下T情况下启用成员函数Fooable:

template <typename T>
class Bar
{
public:
    template // ???
        requires Fooable<T>
    void MemFun();
};
Run Code Online (Sandbox Code Playgroud)

在带有概念TS或C++ 2a的C++ 17中是否可行?

c++ c++-concepts c++17 c++20

7
推荐指数
1
解决办法
218
查看次数

为什么从采用std :: ranges :: output_range的算法返回std :: ranges :: safe_iterator_t而不是std :: ranges :: safe_subrange_t

我正在编写一种算法,该算法将一些数据写入提供的输出范围(问题的初始文本包括具体内容,并将注释中的讨论变成错误的方向)。我希望它在API中与标准库中的其他范围算法尽可能接近。

我查看了的实例的最新草案std::ranges::output_range,发现只有2种算法:

他们俩都回来了std::ranges::safe_iterator_t。我认为返回是合乎逻辑的std::ranges::safe_subrange_t。即使您写入输出流,在这种情况下,您仍然可以返回迭代器-前哨对,并将该范围向下传递。

我找到了P0970,看起来好像std::ranges::safe_subrange_t是后来添加的。也许算法根本没有更新?还是有其他原因?

c++ iterator range c++20

6
推荐指数
1
解决办法
513
查看次数