嵌套vector引发Segmentation Fault问题求助
首先,导致Segmentation Fault的核心原因是你初始化result2的方式和std::back_inserter的用法冲突了:
你写了:
std::vector<std::vector<double>> result2(N);
这行代码会直接创建一个包含**N个空的std::vector<double>**的容器。之后你又用std::back_inserter(result2)往容器末尾插入N个新生成的向量,最终result2的大小会变成2*N。而你尝试访问的result2[0]是最初创建的那个空向量,对空向量执行[0]访问自然会触发越界,导致段错误。
修复方法二选一:
方法1:初始化空容器,用back_inserter填充
把result2初始化为空,让back_inserter负责插入所有N个元素:
int main(){ int N = 5; std::vector<std::vector<double>> result2; // 初始为空 result2.reserve(N); // 可选:预分配空间提升性能 std::generate_n(std::back_inserter(result2), N, gen_rand_vec()); std::cout << result2[0][0] <<std::endl; }
方法2:直接初始化容器大小,用普通迭代器填充
如果想保持容器初始大小为N,就不要用back_inserter,直接传入result2.begin():
int main(){ int N = 5; std::vector<std::vector<double>> result2(N); std::generate_n(result2.begin(), N, gen_rand_vec()); std::cout << result2[0][0] <<std::endl; }
额外的代码优化建议
除了段错误的问题,你的代码还有几个可以改进的地方:
std::bind1st已被弃用,且类型不匹配
你用了std::bind1st(std::multiplies<float>(),1/norm),但你的向量元素是double类型,float和double的混合可能导致精度损失,而且bind1st在C++11之后已经被std::bind或lambda替代,更推荐用lambda:std::transform(result.begin(), result.end(), result.begin(), [norm](double x) { return x / norm; });当前的球面随机向量生成方法并非均匀分布
你现在的方法是生成三个[-1,1]的均匀分布分量再归一化,这种方式得到的向量在球面上的分布是不均匀的(两极附近的点会更密集)。正确的均匀分布生成方法可以用正态分布采样后归一化:#include <random> // ... struct gen_rand_vec{ std::normal_distribution<double> dist{0,1}; std::mt19937 rng{std::random_device{}()}; // 更优质的随机数生成器 std::vector<double> operator()(){ std::vector<double> result = {dist(rng), dist(rng), dist(rng)}; double norm = l2_norm(result); std::transform(result.begin(), result.end(), result.begin(), [norm](double x) { return x / norm; }); return result; } };替换老旧的
rand()rand()的随机质量较差,推荐用C++11引入的<random>库中的随机数生成器(如上面的std::mt19937)。
内容的提问来源于stack exchange,提问作者bernhard_e

