我本来以为有人能做到这一点?然而,情况似乎并非如此。为什么?或者我做错了什么?
#include <vector>
#include <initializer_list>
#include <iostream>
using namespace std;
void fn(std::initializer_list<int> i)
{
for(int ivalue:i)
{
cout << ivalue << endl;
}
}
int main()
{
fn({1,2,3});
fn(vector<int>{4,5,6})
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我问这个问题的原因是因为我有一个类需要一个初始化列表,并且我是从它派生的,但需要在将初始化列表传递到基类之前对其进行处理。我怎样才能做到这一点?
当我使用 g++ 编译 C++ 程序时
warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
for ( int i=0; i< myvec->size(); i++ ){
^
Run Code Online (Sandbox Code Playgroud)
其中myvec是 的对象std::vector<float>。
为了迭代 std::vector 中的元素,我需要处理警告吗?谢谢。
我有一个字节向量 (std::vector ): [1,1,1,9,9,9,1,1,1]
我想用未知长度的字节替换字节 3-6(我会在运行时知道)。因此向量的长度可能会增长、缩短或保持不变。但我知道我想要替换的字节的起点和终点。
我可以使用擦除或插入来调整大小,然后将新数据循环到旧数据上。
std::replace 进行搜索并替换匹配字节,而我知道要替换哪些字节。而 std::replace 似乎只替换一个元素。我想用数据块替换。
当然有一个 std 函数可以“巧妙”地做到这一点?(如果我愿意的话,我会叫你雪莉)。
为了了解std::vector<int>我写的内存消耗:
std::cout << sizeof(std::vector<int>) << std::endl;
Run Code Online (Sandbox Code Playgroud)
这产生32. 我试图理解这个价值从何而来。有些人查看了std::vector存储指针的源代码_MyFirst,_MyLast并_MyEnd解释了 24 字节的内存消耗(在我的 64 位系统上)。
最后一个字节怎么样8?据我了解,存储的分配器不使用任何内存。另外,这可能是实现定义的(是吗?),所以这可能有帮助:我正在使用 MSVC 2017.5。我不保证通过查看代码找到所有成员;该代码对我来说看起来非常混乱。
一切似乎都很好地对齐,但答案可能如下?:为什么结构体的 sizeof 不等于每个成员的 sizeof 之和?。但我用一个简单的测试它struct Test { int *a, *b, *c; };满足sizeof(Test) == 24.
一些背景
在我的程序中,我将有很多向量,但似乎其中大部分都是空的。这意味着关键的内存消耗来自空状态,即堆分配的内存不是那么重要。
一个简单的“仅用于此用例”向量很快就实现了,所以我想知道我是否遗漏了任何东西,无论如何我都需要 32 字节的内存,即使使用我自己的实现(注意:我很可能不会实现我自己的,这只是好奇心)。
更新
我用以下结构再次测试了它:
struct Test
{
int *a, *b, *c;
std::allocator<int> alloc;
};
Run Code Online (Sandbox Code Playgroud)
现在给了sizeof(Test) == 32。看起来,即使std::allocator没有消耗内存的成员(我认为),它的存在也会将Test …
据我了解,在 C++ 中,std::vector::resize当新大小较小时不分配新内存。此外,如果元素类型是具有析构函数的用户定义类,则可以为调整大小中“丢失”的每个元素调用该析构函数,因此在这种情况下,运行时间将与大小差异呈线性关系。
但是,如果元素类型是原语,例如std::vector<int>,则无需调用析构函数。在这种情况下,是否有任何理由认为resize向下不会是 O(1) 时间?
我想实现一个迭代器以在 for range 循环中使用自定义类。迭代器访问基类的内部std::vector并std::unique_ptr返回指向子类的原始指针。
这就是我想出的:
using upBase = std::unique_ptr<Base>;
class Test
{
std::vector<upBase> list;
public:
void Add(upBase&& i) { list.push_back(std::move(i)); }
class iterator
{
upBase* ptr;
public:
iterator(upBase* p) : ptr(p) {}
bool operator!=(const iterator& o) { return ptr != o.ptr; }
iterator& operator++() { ++ptr; return *this; }
Child& operator*() { return *(Child*)(*ptr).get(); }
const Child& operator*() const { return *(Child*)(*ptr).get(); }
};
iterator begin() { return iterator(&list[0]); }
iterator end() { return iterator(&list[list.size()]); } …Run Code Online (Sandbox Code Playgroud) 有没有办法将已经初始化的数据移动到 a 中std::vector?
这是我自己的简单vec课程:
template<typename T>
class vec final
{
std::unique_ptr<T[]> pValues;
size_t size = 0;
public:
std::span<T> span() const { return std::span<int>(pValues.get(), size); }
vec(T* p, size_t sz) : size(sz) { pValues.reset(p); }
};
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它将获得传递给它的内存的所有权:
int main()
{
constexpr size_t count = 99;
auto orig = std::make_unique<int[]>(count);
{
std::span<int> orig_(orig.get(), count);
std::iota(orig_.begin(), orig_.end(), -1);
assert((orig_[0] == -1) && (orig_[1] == 0) && (orig_[98] == 97));
}
vec<int> nums(orig.release(), count);
auto nums_ = nums.span();
assert((nums_[0] == …Run Code Online (Sandbox Code Playgroud) 我正在使用一些代码,通过将其地址与描述数据std::vector范围的地址进行比较,检查是否在恒定时间内包含给定元素。vector然而我怀疑,虽然它有效,但它依赖于未定义的行为。如果该元素不包含在 中,vector则不允许进行指针比较。
bool contains(const std::vector<T>& v, const T& a) {
return (v.data() <= &a) && (&a < v.data() + v.size());
}
Run Code Online (Sandbox Code Playgroud)
我相信这是未定义的行为吗?如果是这样,有没有办法在不大幅改变代码时间复杂度的情况下做同样的事情?
我有以下代码:
#include <vector>
#include <iostream>
std::vector <int> a;
int append(){
a.emplace_back(0);
return 10;
}
int main(){
a = {0};
a[0] = append();
std::cout << a[0] << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该函数append()的副作用是将向量大小增加一。由于向量的工作方式,当超出其容量时,可能会触发其内存的重新分配。
因此,在执行 时a[0] = append(),如果发生重新分配,则 thena[0]无效并指向向量的旧内存。因此,您可以预期向量最终会变为,{0, 0}而不是{10, 0},因为它分配给旧向量a[0]而不是新向量。
让我感到困惑的是,这种行为在 C++14 和 C++17 之间发生了变化。
在 C++14 上,程序将打印 0。在 C++17 上,它将打印 10,这意味着a[0]实际上分配了 10。所以,我有以下问题,但我找不到答案:
a[0]在评估赋值表达式的 RHS 之后评估 的内存地址?C++14 之前是否对此进行了评估,这就是它发生变化的原因?https://en.cppreference.com/w/cpp/container/vector说:
矢量的存储是自动处理的,根据需要扩展和收缩。
但我找不到“根据需要”发生收缩的情况。任何收缩操作都不会收缩 std::vector 的容量:
清除():
保持向量的capacity()不变
当调整到更小的尺寸时,向量容量永远不会减少,因为这会使所有迭代器无效
擦除():
在擦除点或擦除点之后使迭代器和引用无效,包括 end() 迭代器。
这意味着擦除点之前的迭代器和引用不会失效,如果容量更改则不会出现这种情况。
迭代器和对最后一个元素的引用以及 end() 迭代器均无效。
这同样适用于此。
Shrink_to_fit() 确实收缩了 std::vector,但它是在 C++11 中添加的,并且上面的句子(“并且收缩”)没有标记为仅适用于 C++11 及更高版本。此外,对shrink_to_fit()的显式调用不是自动的(“矢量的存储是自动处理的”)并且不会“根据需要”发生。
那么 std::vector 何时自动收缩其存储空间呢?