- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
当我用 valarray
写一个简单的算术表达式时并将结果分配给 auto
当我尝试在 gcc 上访问结果时出现段错误。
#include <iostream>
#include <valarray>
using std::ostream; using std::valarray;
ostream& operator<<(ostream&os, const valarray<double>&vs) {
os << "[";
for(auto&v : vs) os << v << " ";
return os << "]";
}
int main() {
valarray<double> a{ 1.0, 2.0, 3.0, 4.0 };
std::cout << "a: " << a << "\n";
valarray<double> b{ 2.0, 4.0, 6.0, 8.0 };
std::cout << "b: " << b << "\n";
valarray<double> c{ 2.0, 1.5, 0.5, 0.25 };
std::cout << "c: " << c << "\n";
valarray<double> x = ( a + b ) / 2;
std::cout << "x: " << x << "\n";
// this still works:
auto y = ( a + b ) / 2;
// The following will result in a segfault:
std::cout << "y:" << y << "\n";
}
reference表示实现可以选择算术运算重载的返回类型可能不是 valarray
-value 但“表现得像它”的东西:
The operators returning a valarray by value are allowed to return an object of a different type instead. Such a type is required to be implicitly convertible to valarray and be supported as argument for all functions taking valarray& arguments. This allows copy-on-write implementations.
好吧,我的 operator<<
应该要求那种“隐式转换”,不是吗?
那么为什么会出现段错误?
$ ./valarray01.cpp.x
a: [1 2 3 4 ]
b: [2 4 6 8 ]
c: [2 1.5 0.5 0.25 ]
x: [1.5 3 4.5 6 ]
Segmentation fault (core dumped)
gcc version 6.2.0 20160901 (Ubuntu 6.2.0-3ubuntu11~14.04)
当我尝试 clang(在 linux 上,所以可能是 gcc 的 stdlib)时,我对此持怀疑态度......它有效:
clang version 3.9.1-svn288847-1~exp1 (branches/release_39)
$ ./valarray01.cpp.x
a: [1 2 3 4 ]
b: [2 4 6 8 ]
c: [2 1.5 0.5 0.25 ]
x: [1.5 3 4.5 6 ]
y:[1.5 3 4.5 6 ]
好吧,在我提交 gcc-bug 之前……我做错了什么吗?是我的auto
邪恶的?还是真的是 gcc?
最佳答案
这是因为 GCC 的 valarray
实现使用 Expression Templates避免为算术表达式的中间结果创建临时对象。表达式模板和 auto
不要混合好。
发生的是 ( a + b )
不立即执行乘法,而是创建一个“闭包”对象,该对象具有对 a
的引用和 b
.实际乘法将被延迟,直到在需要结果的上下文中使用闭包。接下来,表达式的其余部分 ( a + b ) / 2
创建第二个闭包对象,该对象包含对第一个闭包对象的引用,以及对值 2
的引用.然后使用第二个闭包对象来初始化一个由 auto
推导出的类型的变量。 :
auto y = ( a + b ) / 2;
所以 y
是一个闭包对象,它引用了第一个闭包和 int
有值 2
.但是,第一次关闭和int
value 都是临时变量,在语句末尾超出范围。这意味着 y
有两个悬空引用,一个临时关闭和一个临时 int
.当您尝试使用 y
在 cout
声明它被转换为 valarray<double>
它试图评估乘法和除法的结果。该评估遵循悬空引用并尝试访问不再存在的临时对象。这意味着未定义的行为。
我正在为 GCC 开发一个补丁,这将有助于使这样的代码更不容易出错(对于 Bug 83860 ),尽管结合 auto
仍然很脆弱带有表达式模板。
如果您不使用 auto
,代码可以正常工作即
std::valarray<double> y = (a+b)/2;
这里的表达式模板在临时对象超出范围之前被评估,因此没有悬空引用。
这个特殊的例子可以通过编译 -fstack-reuse=none
来“工作”。这禁用了重用临时对象使用的堆栈空间的优化。这意味着悬空引用在其生命周期结束后仍可用于访问临时对象。这只是一个创可贴,而不是真正的解决方案。真正的解决方案是不要将表达式模板和 auto
混合使用。 .
关于c++ - 具有算术运算返回类型的 valarray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42726804/
是的,这个has been asked before ,答案是: valarrays (value arrays) are intended to bring some of the speed of
看完这篇http://gcc.gnu.org/ml/libstdc++/2000-q1/msg00123.html ,似乎标准不能保证使用 valarrays 的 valarrays 是安全的。但是当
STL 中valarray::min 和valarray::max 函数的时间复杂度是多少? 此外,什么是查找各种其他 STL 组件的时间/空间复杂性的良好来源? 最佳答案 O(N) 这些函数不会缓存
这是我在这里的第一篇文章,但我经常阅读这里的各种主题。 现在我被 c++ 的编程问题困住了,它基本上是一个名为“Pair”的模板类,它应该包含 2 个 valarrays 的整数,然后包含在另一个名为
出于兼容性目的,我正在开发一个具有 C 接口(interface)的库 void interface(double* context, size_t num_elements); 而 context
我有一些数据存储在 std::vector 中.我用它来创建一个 std::valarray来 self 的 std::vector . std:valarray corpX(corps_tmp[i]
当我将 valarray 除以它的第一个元素时,只有第一个元素变为 1,其他元素保持其原始值。 #include #include using namespace std; int main()
为什么 std::valarray 不支持自定义分配器?它的内存管理是怎么设计的?是否使用了基于new 或malloc 的分配器?所有其他容器通常都提供指定自定义分配器的可能性。比如说,libstdc
valarray 是否有连续内存对齐? 我想通过传递 &myValarray[0] 将一个 valarray 传递给一个只接受指针的函数(来自 IPPS)。但因此我应该确定,valarray 的内存对
以下程序: #include #include using namespace std; int main() { int init[] = {1, 1}; // Example 1 va
当我用 valarray 写一个简单的算术表达式时并将结果分配给 auto当我尝试在 gcc 上访问结果时出现段错误。 #include #include using std::ostream;
std::valarray myArray(3)产生 valarray长度为 3,初始化为零。 std::valarray myArray(1,3)产生 valarray长度为 3,初始化为 1。 s
我们可以初始化一个valarray来自基本的用户定义数组,如下所示: int arr[3]={0}; valarray test(arr, sizeof(arr)/sizeof(int)); 我们怎样
在下面的类中,当我尝试为 operator [] 返回 std::valarray& 时,它说:invalid initialization of std::valarray& from R - 值引
我发布了一个用 C++ 编写的简单的 n-body 类 here在代码审查中。 我被告知要使用 std::valarray 而不是普通的 std::array ,目的是我可以重写一些目前看起来像这样的
我在一个列表中有很多数据,比如每个元素有几千字节,我想逐个提取以进行一些数字处理。这些数据最初存储为 float[]。由于处理涉及大量索引和全局计算,我认为 valarray 可能易于编程。但是如果我
您好,我想构建一个辅助类来初始化一个 STL valarray。我想要的是执行以下操作: std::valarray vec(3); vlist_of(vec)(2)(3)(5); 所以我可以只使用一
我正在寻找静态大小的 std::valarray 实现。 我自己实现应该很容易,但我需要 constexpr 操作(加法、减法等),这有点无聊/容易出错,所以我在这里问一下是否有流行的实现。 如果我必
代码: #include #include using namespace std; int main() { valarray v0(2, 4); valarray v1; v
这可能是个愚蠢的问题。 关于 this我读过的网站 The valarray specification allows for libraries to implement it with sever
我是一名优秀的程序员,十分优秀!