尝试将vector作为类成员传递引用,为何实际是传值导致修改无效?
问题:类中操作vector副本而非原容器的原因与解决办法
我尝试将vector作为类成员以引用传递,但实际是传值传递。编写的类中Swap_up方法用于修改vector元素位置,执行时类内打印显示元素已上移,但main函数中原vector的元素回到初始位置,操作的是副本而非原容器,请问哪里出错了?
原代码:
#include <iostream> #include <string> #include <vector> using namespace std; class Example { int x, y; vector<vector<string>> chart; public: Example(int i, int j, vector<vector<string>>& arr); void Swap_up(); }; Example::Example(int i, int j, vector<vector<string>>& arr) :x(i), y(j), chart(arr) { } void Example::Swap_up() { if (x - 1 >= 0 && chart[x - 1][y].at(0) == ' ') { string temp = chart[x-1][y]; chart[x - 1][y] = chart[x][y]; chart[x][y] = temp; x = y - 1; for (int i = 0; i < chart.size(); i++) { for (int j = 0; j < chart[0].size(); j++) { cout << '[' << chart[i][j] << ']'; } cout << endl; } cout << endl; } else cout << "Invalid move" << endl; } int main() { int chart_height; int chart_width; cout << "Enter height of the chart in number of spaces (Minimum number of spaces is 7)" << endl; cin >> chart_height; cout << "Enter width of the chart in number of spaces (Minimum number of spaces is 7)" << endl; cin >> chart_width; vector<vector<string>> chart; chart.resize(chart_height); for (int i = 0; i < chart_height; i++) chart[i].resize(chart_width); for (int i = 0; i < chart_height; i++) { for (int j = 0; j < chart_width; j++) { if (chart[i][j] == "") chart[i][j].insert(0, 3, ' '); } } chart[6][5] = "EXA"; for (int i = 0; i < chart_height; i++) { for (int j = 0; j < chart_width; j++) { cout << '[' << chart[i][j] << ']'; } cout << endl; } cout << endl; Example Exa1(6, 5, chart); Exa1.Swap_up(); for (int i = 0; i < chart_height; i++) { for (int j = 0; j < chart_width; j++) { cout << '[' << chart[i][j] << ']'; } cout << endl; } chart.clear(); chart.resize(0); return 0; }
错误原因:
你类中的chart成员是值类型的vector容器,不是引用或指针。构造函数里的chart(arr)是调用vector的拷贝构造函数,把传入的原vector完整复制了一份到类成员里——相当于类操作的是原vector的"双胞胎副本",所有修改只在副本上生效,原vector自然不会有变化。
另外提个小问题:原代码中Swap_up里的x = y - 1;是逻辑错误,应该写成x = x - 1;,否则移动后x的位置会乱掉。
解决办法
办法1:把类成员改成引用类型
直接让类成员绑定到原vector的引用,这样所有操作都会直接作用在原容器上:
class Example { int x, y; vector<vector<string>>& chart; // 修改为引用类型 public: Example(int i, int j, vector<vector<string>>& arr); void Swap_up(); }; // 引用必须在初始化列表中完成绑定,不能在构造函数体内赋值 Example::Example(int i, int j, vector<vector<string>>& arr) :x(i), y(j), chart(arr) { }
注意:要保证原vector的生命周期比类对象长,否则会出现悬空引用,导致程序崩溃。
办法2:把类成员改成指针类型
如果担心生命周期问题,用指针持有原vector的地址也是可行的:
class Example { int x, y; vector<vector<string>>* chart; // 修改为指针类型 public: Example(int i, int j, vector<vector<string>>& arr); void Swap_up(); }; Example::Example(int i, int j, vector<vector<string>>& arr) :x(i), y(j), chart(&arr) { }
然后修改Swap_up里的访问方式,把.改成->或者先解引用指针:
void Example::Swap_up() { if (x - 1 >= 0 && (*chart)[x - 1][y].at(0) == ' ') { string temp = (*chart)[x-1][y]; (*chart)[x - 1][y] = (*chart)[x][y]; (*chart)[x][y] = temp; x = x - 1; // 修正逻辑错误 for (int i = 0; i < chart->size(); i++) { for (int j = 0; j < (*chart)[0].size(); j++) { cout << '[' << (*chart)[i][j] << ']'; } cout << endl; } cout << endl; } else cout << "Invalid move" << endl; }
内容的提问来源于stack exchange,提问作者b23
相关产品推荐
相关产品推荐

