C++ 这三种创建向量的方法有何不同?

C++ 这三种创建向量的方法有何不同?,c++,vector,c++14,C++,Vector,C++14,在处理提交文件时,我发现自己的行为我不理解。我有三种从输入填充矩阵的方法。其中一个可以工作,其中一个编译并运行,但产生了一个稍有错误的结果,其中一个因free():无效指针而崩溃 为了简单起见,我将关于错误结果的部分排除在这个问题之外,并将代码简化为只读取输入。让我们暂时忽略输出,只考虑两个测试用例的错误消息: root@41d06f89ab19:/code#gp so1.cpp&./so1.exe so1.txt root@41d06f89ab19:/code#gp so2.cpp&./so2

在处理提交文件时,我发现自己的行为我不理解。我有三种从输入填充矩阵的方法。其中一个可以工作,其中一个编译并运行,但产生了一个稍有错误的结果,其中一个因
free():无效指针而崩溃

为了简单起见,我将关于错误结果的部分排除在这个问题之外,并将代码简化为只读取输入。让我们暂时忽略输出,只考虑两个测试用例的错误消息:

root@41d06f89ab19:/code#gp so1.cpp&./so1.exe so1.txt
root@41d06f89ab19:/code#gp so2.cpp&./so2.exe so2.txt
分段故障(堆芯转储)
root@41d06f89ab19:/code#gp so3.cpp&./so3.exe so3.txt
root@41d06f89ab19:/code#gp so1.cpp&./so1.exe so1_2.txt
free():无效指针
中止(堆芯转储)
root@41d06f89ab19:/code#gp so2.cpp&./so2.exe so2_2.txt
分段故障(堆芯转储)
root@41d06f89ab19:/code#gp so3.cpp&./so3.exe so3_2.txt
显然,这三个代码片段的行为并不相同。 考虑下面的三个文件。它们的语义有什么不同?为什么它们不完全相同

//文件so1.cpp-
#包括
#包括
#包括
#包括
#包括
#包括

对于再现性:


问题不在于如何创建
问题在于使用
矩阵[row]
访问不存在的元素

这里

您没有填充矩阵<代码>保留
仅为元素分配空间。它不会添加元素或更改向量大小<代码>矩阵
的元素为零,并且在第一个代码中不会改变。在未定义的行为中访问超出边界的向量

如果您想使用
n
行创建
矩阵
,则需要使用
n
元素对其进行初始化:

VVI matrix{n};

或者。。。在第二个代码中,使用大小为
n
std::vector
s的
n
元素正确初始化
矩阵

VVI matrix(n, std::vector<int>(n));
VVI矩阵(n,std::vector(n));

TL;博士:VVI矩阵;矩阵.储备(n)--保留区不在向量中创建元素。@PaulMcKenzie我在编写此代码时就意识到了这一点,这就是为什么我要创建一个新的向量,以便在第一次写入时分配给矩阵[行]。或者我没有做我认为我正在做的事情?是的,这是未定义的行为,不同的崩溃可能只是由于使用移动或复制分配operators@lucidbrot未定义的行为是未定义的。试图弄清楚会发生什么是没有意义的。如果我在VisualC++调试模式下运行代码,当你试图访问<代码>矩阵[RO] 时,我可能会得到一个大的<代码> AsSturi> <代码>框,而另一个编译器或不同编译器选项,则会产生不同的结果。严格来说,有两种可能的观点。您可以尝试理解为什么它会在一种情况下出现故障,而在另一种情况下不会出现故障,但是您需要研究正在使用的实现和编译器的输出。您只能了解针对此特定体系结构的特定编译器。另一种观点是:正确的C++编译无处不在,我们不需要关心实现细节,你的代码不正确C++代码谢谢。这是一个明显的错误,但我还是和一些朋友花了一个小时。。这意味着当矩阵作为正确大小的向量存在时,这两个错误的代码片段是等价的?我现在要问的是:不同的行为仅仅是由于未定义的行为,还是也有意义上的差异?@lucidbrot说实话,我没有完全理解这个问题。您指的是
std::vector myvec(n)之间的差异;矩阵[行]=myvec
矩阵[行]=std::vector(n)?它们应该是一样的,但在UB面前,一切都是一样的,而不是在同一时间;)。明天,你可能会在另一个案例中得到一个segfault,或者根本没有segfault。
VVI matrix;
matrix.resize(n);
VVI matrix(n, std::vector<int>(n));