无法修改类中变量值,main函数始终获取原始值的问题
问题
我定义了一个包含若干变量的类,在函数里能正常读取这些变量,也看似成功把它们更新成了新值,但回到main()函数里获取的始终是原始值,实在找不到问题所在。
环境:Windows 10 系统,Visual Studio 2022
代码如下:
header.h
#pragma once #include <string> #include "gmp.h" class my_class { public: const static int CPU_GRP_SIZE = 16; mpz_t tempx, tempy; my_class() { mpz_init_set_str(tempx, "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16); mpz_init_set_str(tempy, "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16); } }; void AddDirect(mpz_t p2x, mpz_t p2y);
main.cpp
#include <string> #include <iostream> #include <gmp.h> #include "header.h" void main() { my_class secp; int hLength = (secp.CPU_GRP_SIZE / 2 - 1); mpz_t point2x, point2y; mpz_init_set_str(point2x, "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", 16); mpz_init_set_str(point2y, "1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a", 16); AddDirect(point2x, point2y); std::cout << "+++++++++++++ main \n"; mpz_out_str(stdout, 16, secp.tempx); std::cout << " \n"; } void AddDirect(mpz_t p2x, mpz_t p2y) { my_class secp; mpz_t point2x, point2y; mpz_init_set(point2x, p2x); mpz_init_set(point2y, p2y); // --------------------------- mpz_set(secp.tempx, point2x); mpz_set(secp.tempy, point2y); //------------------ std::cout << "adddirect secp.tempx\n"; mpz_out_str(stdout, 16, secp.tempx); std::cout << " \n"; }
预期输出:
adddirect secp.tempx c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 +++++++++++++ main c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
实际输出:
adddirect secp.tempx c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 +++++++++++++ main 79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
解决方案
问题核心在于:AddDirect函数内部新建了一个独立的my_class对象,和main()里的secp完全是两个不同的实例。你在AddDirect里修改的是这个局部对象的tempx/tempy,修改完成后这个局部对象就被销毁了,main()里的原对象根本没被改动。
有两种常见修复方式:
方法1:将对象通过引用传入函数
修改AddDirect的参数,让它接收my_class的引用,这样函数里操作的就是main()里的原对象:
修改后的header.h
#pragma once #include <string> #include "gmp.h" class my_class { public: const static int CPU_GRP_SIZE = 16; mpz_t tempx, tempy; my_class() { mpz_init_set_str(tempx, "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16); mpz_init_set_str(tempy, "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16); } }; // 修改函数参数,添加my_class引用 void AddDirect(my_class& secp, mpz_t p2x, mpz_t p2y);
修改后的main.cpp
#include <string> #include <iostream> #include <gmp.h> #include "header.h" int main() // 标准C++要求main返回类型为int { my_class secp; int hLength = (secp.CPU_GRP_SIZE / 2 - 1); mpz_t point2x, point2y; mpz_init_set_str(point2x, "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", 16); mpz_init_set_str(point2y, "1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a", 16); // 传入secp对象的引用 AddDirect(secp, point2x, point2y); std::cout << "+++++++++++++ main \n"; mpz_out_str(stdout, 16, secp.tempx); std::cout << " \n"; // 释放mpz资源,避免内存泄漏 mpz_clear(point2x); mpz_clear(point2y); return 0; } void AddDirect(my_class& secp, mpz_t p2x, mpz_t p2y) { // 不需要再新建my_class对象,直接用传入的引用 mpz_t point2x, point2y; mpz_init_set(point2x, p2x); mpz_init_set(point2y, p2y); mpz_set(secp.tempx, point2x); mpz_set(secp.tempy, point2y); std::cout << "adddirect secp.tempx\n"; mpz_out_str(stdout, 16, secp.tempx); std::cout << " \n"; // 释放局部mpz资源 mpz_clear(point2x); mpz_clear(point2y); }
方法2:将AddDirect改为类的成员函数
既然AddDirect是操作my_class对象的方法,直接把它定义成类的成员函数更符合面向对象设计:
修改后的header.h
#pragma once #include <string> #include "gmp.h" class my_class { public: const static int CPU_GRP_SIZE = 16; mpz_t tempx, tempy; my_class() { mpz_init_set_str(tempx, "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16); mpz_init_set_str(tempy, "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16); } // 定义成员函数 void AddDirect(mpz_t p2x, mpz_t p2y); };
修改后的main.cpp
#include <string> #include <iostream> #include <gmp.h> #include "header.h" int main() { my_class secp; int hLength = (secp.CPU_GRP_SIZE / 2 - 1); mpz_t point2x, point2y; mpz_init_set_str(point2x, "c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", 16); mpz_init_set_str(point2y, "1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a", 16); // 调用成员函数 secp.AddDirect(point2x, point2y); std::cout << "+++++++++++++ main \n"; mpz_out_str(stdout, 16, secp.tempx); std::cout << " \n"; mpz_clear(point2x); mpz_clear(point2y); return 0; } // 实现成员函数 void my_class::AddDirect(mpz_t p2x, mpz_t p2y) { mpz_t point2x, point2y; mpz_init_set(point2x, p2x); mpz_init_set(point2y, p2y); // 直接操作当前对象的tempx/tempy mpz_set(tempx, point2x); mpz_set(tempy, point2y); std::cout << "adddirect secp.tempx\n"; mpz_out_str(stdout, 16, tempx); std::cout << " \n"; mpz_clear(point2x); mpz_clear(point2y); }
另外补充两个细节:
- 标准C++中
main函数的返回类型必须是int,不能是void,修改后更规范。 - 使用
mpz_t后记得调用mpz_clear释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Josh Wert
相关产品推荐
相关产品推荐

