在我看来,它们都有相同的功能,除了 std::vector 似乎更灵活,所以什么时候我需要使用数组,我可以只使用 std::vector 吗?这不是一个新问题,原来的问题没有我正在寻找的答案
我对 C++ 有点生疏——20 年前就用过它。我试图理解为什么 std::vector 在以下代码中比本机数组慢得多。谁能给我解释一下吗?我更喜欢使用标准库,但不以牺牲性能为代价:
向量:
const int grid_e_rows = 50;
const int grid_e_cols = 50;
int H(std::vector<std::vector<int>> &sigma) {
int h = 0;
for (int r = 0; r < grid_e_rows; ++r) {
int r2 = (r + 1) % grid_e_rows;
for (int c = 0; c < grid_e_cols; ++c) {
int c2 = (c + 1) % grid_e_cols;
h += 1 * sigma[r][c] * sigma[r][c2] + 1 * sigma[r][c] * sigma[r2][c];
}
}
return -h;
}
int …Run Code Online (Sandbox Code Playgroud) 据我所知,.reserve()为向量保留内存而不实际修改其大小。但这是如何实现的呢?如何只保留内存而不分配内存呢?
编辑:我具体询问如何保留内存而不分配内存,而不是std::vector一般如何工作
我想知道是否可以std::vector<std::vector<int>> 通过迭代器访问元素:我无法理解为什么这不能编译:
#include<vector> \n#include<iostream> \n\nstd::vector<std::vector<int>> vec {{1,2},{3,4}} ; \n\n// to access the single vector \nauto it = vec.begin() ; \n\n// to access the element of the vector \nauto iit = it.begin() ; \n\nRun Code Online (Sandbox Code Playgroud)\n这是我得到的错误:
\nprova.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\nprova.cpp:10:15: error: \xe2\x80\x98class __gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> > >\xe2\x80\x99 has no member named \xe2\x80\x98begin\xe2\x80\x99\n 10 | auto iit = it.begin() ;\nRun Code Online (Sandbox Code Playgroud)\n forward_list<int> listOne;
forward_list<int> listTwo;
vector<int> arr = {2,4,3};
forward_list<int>::iterator it;
Run Code Online (Sandbox Code Playgroud)
在上面提到的代码中,我想插入一个std::vectorinlistOne并尝试使用insert_after函数。
it = listOne.begin();
listOne.insert_after(it,arr);
Run Code Online (Sandbox Code Playgroud)
但这没有用。
我想知道,有没有办法std::vector在 a 中添加 a 或 数组std::forward_list而不需要任何循环?
void set_fee(Patron p, int fee)
{
for (Patron x : patrons)
{
if (p.get_name() == x.get_name()) x.set_fee(fee);
}
for (int i = 0; i < patrons.size(); i++)
{
if (patrons[i].get_name() == p.get_name()) patrons[i].set_fee(fee);
}
}
Run Code Online (Sandbox Code Playgroud)
这patron只是我创建的一些类,这里的任何函数都不重要,get_name()只是返回对象的名称并将对象的费用set_fee(fee)设置为费用。fee
但是有人知道为什么第一个循环不起作用但第二个循环起作用吗?p我基本上只是想在向量内部查找patrons,一旦找到它,我想更改向量内赞助对象的费用,但第一种方法不起作用,为什么?
我试图理解移动语义的通用规则。特别是容器和包含的元素。
原因是我试图在所有权和迭代器失效的背景下理解移动。为此,我将经历一些复杂性不断增加的案例,涉及典型容器、通用包含类型T、通用g和f函数。(也许一个重要的额外细节是,f实际上可能会或可能不会执行移动操作,或者它可能在运行时是偶然的。)
这个想法是引入案例3,这是这个问题的核心。
首先是一个相当没有争议的案例,这是可以的:
std::vector<T> v(100, t);
f(std::move(v));
v = make_a_vector();
Run Code Online (Sandbox Code Playgroud)
然而,移动后使用可能是臭代码
std::vector<T> v(100, t);
f(std::move(v));
g(v);
Run Code Online (Sandbox Code Playgroud)
我想大多数人都同意上面的做法是不行的。规则是(据我所知)移动后的唯一操作应该是赋值。我认为这尤其是因为它没有记录(未定义但有效的状态)移出向量的状态是什么(或者即使它被移动了)。因此,充其量v是空的,最坏的v情况是未指定的状态,因此g可以在此范围内执行未指定的操作。
std::vector<T> v(100, t);
f(std::move(v));
v.resize(120);
Run Code Online (Sandbox Code Playgroud)
这是对的吗?这不是一项任务,但resize没有先决条件。(发现这个Can I resize a vector that was moving from?)
现在是真正棘手的情况。
std::vector<T> v(100);
h(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()));
v.resize(120);
Run Code Online (Sandbox Code Playgroud)
(这里,h是一个采用迭代器的函数,假设它隐式引用 range 。 [iterator1, iterator2))
这是正确的代码吗?原因是.resize似乎要播放、移动、交换和复制类型为移出的对象T。
总而言之,调整其元素已(可能)移出的向量的大小是否正确?
编辑:为了论证,让我们指定函数的签名,以防它们与答案相关:
template<class …Run Code Online (Sandbox Code Playgroud) 这是重现我想要理解的内容的代码:
首先,我有一个带有指针作为属性的类,并将其构造函数设置为默认值。
class PointExampl {
private:
int* p_ = new int;
public:
PointExampl() = default;
int* returnp() {return p_;};
};
Run Code Online (Sandbox Code Playgroud)
这是main.cpp:
int main() {
std::vector<std::vector<PointExampl>> vec;
vec.resize(10, std::vector<PointExampl>(10));
for(int i = 0; i < vec.size(); i++)
std::cout << vec[i][0].returnp() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
0x1695c8e1920
所以这就是我不明白的 std::resize 。每行的每个第一个对象不应该有不同的指针吗?
这是我在一些关于生命游戏的课程项目中使用 std::vector 遇到的问题的简化。我原本期望有一个完整的新指针矩阵,但得到的是第一行指向其他行的指针的副本。
我也使用 c++14 如果这有什么关系的话。
我见过一些类似的问题,但我无法让它发挥作用。
这失败了:
std::vector<void (CChristianLifeMinistryEntry::* pfnSetAssignName)(CString)> = xx;
Run Code Online (Sandbox Code Playgroud)
我想要一个向量,以便我可以用一系列&CChristianLifeMinistryEntry::SetXXX函数预先填充它。这样我就可以快速确定在for循环中使用的正确函数。
struct MZEntry
{
uint32_t machineID;
bool mode;
uint32_t area;
uint32_t occupancy;
using ZList = std::vector<uint32_t>;
ZList authorisationZ;
ZList blockExceptionZ;
void clear()
{
machineID = 0;
mode = false;
area = 0;
occupancy = 0;
authorisationZ.clear();
blockExceptionZ.clear();
}
MZEntry(){
clear();
}
MZEntry(const MZEntry& mzEntry)
{
machineID = mzEntry.machineID;
mode = mzEntry.mode;
area = mzEntry.area;
occupancy = mzEntry.occupancy;
authorisationZ = mzEntry.authorisationZ;
blockExceptionZ = mzEntry.blockExceptionZ;
}
};
Run Code Online (Sandbox Code Playgroud)
我的代码中有上述结构。我显式声明复制构造函数有什么好处吗?
假设我有两个变量
MZEntry entry_1;
MZEntry entry_2;
Run Code Online (Sandbox Code Playgroud)
如果我这样做entry_1 = entry_2,中的所有字段都会entry_2被复制以entry_1包含其中的向量吗?
或者是否需要显式的复制构造函数。上面的显式复制构造函数是否更有效?