Embarcadero C++7.30下std::slice_array拷贝构造链接错误求解
问题性质判定
该问题属于Embarcadero C++ 7.30 for Win32的STL实现+编译器重载决议的缺陷:
- 按照C++标准要求,
std::slice_array作为valarray的切片代理类,其拷贝构造函数必须为slice_array(const slice_array&)的const引用参数版本,且该构造函数具有公开访问权限。 - 该编译器在处理临时
slice_array对象作为构造函数参数传参时,错误地尝试匹配不存在的非const引用参数版本的拷贝构造slice_array(slice_array&),该函数从未在对应版本STL中实现,最终触发链接阶段的未解析外部符号错误。 - 符合标准的编译器(如Visual Studio 2022、GCC、Clang)均可以正常编译运行原代码,不存在该问题。
适配修改方案
核心思路是避免直接存储或拷贝std::slice_array对象,在自定义切片代理类中存储生成切片所需的元信息,仅在需要执行赋值等操作时临时构造slice_array对象,从根源上绕开有缺陷的拷贝逻辑。
修改后的可运行代码如下:
#include <valarray> #include <iostream> using namespace std; void print(const valarray<double> &x) { for (int i = 0; i != x.size(); ++i) cout << x[i] << " "; cout << endl; } struct slice_matrix1d { int nr; std::valarray<double>* src_arr; size_t start_pos; size_t stride; slice_matrix1d(std::valarray<double>* src, size_t start, size_t len, size_t step): src_arr(src), start_pos(start), nr(len), stride(step) {} void operator=(double v) { // 操作时临时生成slice_array,不做持久化存储,无需拷贝 (*src_arr)[std::slice(start_pos, nr, stride)] = v; } }; struct matrix1d { int nr; valarray<double> elem; matrix1d(const std::valarray<double> &sa, int n): elem(sa),nr(n) {} matrix1d subvec(int i, int j) const { std::size_t sub_len = j - i + 1; return matrix1d(elem[std::slice(i, sub_len, 1)], sub_len); } slice_matrix1d subvec(int i, int j) { std::size_t sub_len = j - i + 1; // 直接传递切片元信息构造自定义代理,不拷贝临时slice_array return slice_matrix1d(&elem, i, sub_len, 1); } }; int main() { std::valarray<double> dva = {1,2,3,4,5}; matrix1d vec1(dva, 5); print(vec1.elem); vec1.subvec(1,3) = 0; print(vec1.elem); }
该修改无编译器特定依赖,在所有符合C++标准的编译环境下均可正常运行,编译后执行输出为:
1 2 3 4 5 1 0 0 0 5
内容的提问来源于stack exchange,提问作者ypan1988
相关产品推荐
相关产品推荐

