在C++ 98中,std::vector填充构造函数的原型具有初始化程序的默认值.
explicit vector (size_type n, const value_type& val = value_type(),
const allocator_type& alloc = allocator_type());
Run Code Online (Sandbox Code Playgroud)
C++ 11使用两个原型.
explicit vector (size_type n);
vector (size_type n, const value_type& val,
const allocator_type& alloc = allocator_type());
Run Code Online (Sandbox Code Playgroud)
(在C++ 14中,填充构造函数再次改变,但这不是这个问题的重点.)
参考链接在这里.
为什么C++ 11会弃用默认的初始化值value_type()?
顺便说一句,我尝试编译以下代码clang++ -std=c++11并发出错误,这意味着值类型仍然需要有一个默认构造函数S() {},即默认构造.
#include <vector>
struct S {
int k;
S(int k) : k(k) {} // intentionally remove the synthesized default constructor
};
int main() {
std::vector<S> s(5); // error: no matching …Run Code Online (Sandbox Code Playgroud) 该文件说std::list效率低下:
std :: list是一个非常低效的类,很少有用.它为插入其中的每个元素执行堆分配,因此具有极高的常数因子,特别是对于小数据类型.
评论:这让我感到惊讶.std::list是一个双向链表,所以尽管它的元件结构效率低下,它支持插入/删除在O(1)的时间复杂度,但这种功能在此引用的段落完全忽略.
我的问题:说我需要一个连续的小尺寸均匀元素的容器,这种容器应支持元素插入/为O删除(1)复杂性和不并不需要随机存取(虽然支持随机访问是好的,它不是必须的这里).我也不希望堆分配为每个元素的构造引入高常量因子,至少当元素的数量很小时.最后,只有在删除相应的元素时,迭代器才会失效.显然我需要一个自定义容器类,它可能(或可能不)是双向链表的变体.我该如何设计这个容器?
如果无法实现上述规范,那么也许我应该有一个自定义内存分配器,比如说,指针分配器?我知道std::list将分配器作为其第二个模板参数.
编辑:我知道从工程的角度来看,我不应该太关心这个问题 - 足够快就足够了.这只是一个假设的问题,所以我没有更详细的用例.随意放松一些要求!
编辑2:据我所知,O(1)复杂度的两种算法由于其常数因子的不同而具有完全不同的性能.
c++ stl linked-list abstract-data-type dynamic-memory-allocation
C++标准提案的代码中的"N"和"P"是什么意思?
以下是GCC标准支持状态列表.您可以看到提案类似于"P0245R1"或"N4051"等.(我认为"R"表示"修订").
这个问题是关于C++ 20的[[likely]]/ [[unlikely]]功能,而不是编译器定义的宏.
这个文档(cppreference)只给出了一个将它们应用于switch-case语句的例子.这个switch-case示例与我的编译器完美编译(g ++ - 7.2),所以我假设编译器已经实现了这个功能,尽管它还没有在当前的C++标准中正式引入.
但是当我像这样使用它们时if (condition) [[likely]] { ... } else { ... },我收到了一个警告:
"警告:语句开头的属性被忽略[-Wattributes]".
那么我应该如何在if-else语句中使用这些属性呢?
在std::span 构造函数的文档中,没有一个接受 std::vector 。
那么,这段代码(源页面)是如何编译的?
// createSpan.cpp
#include <algorithm>
#include <iostream>
#include <span>
#include <vector>
int main() {
std::cout << std::endl;
std::cout << std::boolalpha;
std::vector myVec{1, 2, 3, 4, 5};
std::span mySpan1{myVec}; // (1)
std::span mySpan2{myVec.data(), myVec.size()}; // (2)
bool spansEqual = std::equal(mySpan1.begin(), mySpan1.end(),
mySpan2.begin(), mySpan2.end());
std::cout << "mySpan1 == mySpan2: " << spansEqual << std::endl; // (3)
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
即在 (1) 处调用了 std::span 的哪个构造函数?
此代码有效:
// Code A
#include <iostream>
#include <vector>
#include <type_traits>
using namespace std;
template <typename T>
struct S {
template <typename Iter, typename = typename enable_if<is_constructible<T, decltype(*(declval<Iter>()))>::value>::type>
S(Iter) { cout << "S(Iter)" << endl; }
S(int) { cout << "S(int)" << endl; }
};
int main()
{
vector<int> v;
S<int> s1(v.begin()); // stdout: S(Iter)
S<int> s2(1); // stdout: S(int)
}
Run Code Online (Sandbox Code Playgroud)
但是下面的代码不起作用.在下面的代码中,我只想继承std::enable_if,因此如果所选版本具有成员typedef ,则该类is_iter_of将具有成员typedef .typestd::enable_iftype
// Code B
#include <iostream>
#include <vector>
#include <type_traits>
using …Run Code Online (Sandbox Code Playgroud) 我有一个专业化std::basic_string,比如说string_t,它的相同的std::string不同之处在于第三个模板参数是我的自定义分配器.
问题:如何使用C++标准库中已提供的散列函数为此专门化定义散列函数类?
我知道如何定义一个Hash仿函数,但我不知道如何利用现有的std::hash<..>仿函数std来定义我的自定义仿函数.我毫不犹豫地写我自己的哈希运算,知道它是重新发明轮子,是不太可能优于std::hash<std::string>,因为之间的唯一区别string_t,并std::string仅仅是分配器.
cppreference有一些例子,但它们对我没有多大帮助 - 我不想std::string使用我的string_t对象的c_str()方法构造一个临时对象,只是std::hash<std::string>为了获取哈希值而将临时对象提供给它,因为它需要分配临时堆内存.
我正在使用C++ 14,我想坚持使用标准库.
许多消息来源说开放寻址中使用的散列冲突处理方法llvm::StringMap不稳定。当负载因子很高(这是可以想象的)时,据说开放寻址不如链接。
但是如果负载因子很低,那么open-addressing就会有巨大的内存浪费,因为我必须在内存中分配Bucket_number * sizeof(Record)字节,即使大多数bucket没有记录。
所以我的问题是,LLVM 选择开放寻址而不是单独链接的原因是什么?是否仅仅是因为缓存局部性(记录本身存储在存储桶中)获得的速度优势?
谢谢:)
编辑:C++11 标准对链接方法的要求,std::unordered_set而std::unordered_map不是开放寻址。为什么LLVM会选择一种连C++标准都达不到的hash碰撞处理方式?llvm::StringMap 是否有任何特殊用例可以保证这种偏差?(编辑:这张幻灯片比较了几种 LLVM 数据结构与 STL 对应数据结构的性能)
另一个问题,顺便说一句:
如何llvm::StringMap保证键的哈希值在增长时不会重新计算?该手册说:
哈希表增长不会重新计算表中已有字符串的哈希值。