1、Numpy共享内存的情况:
array1 = np.array([1, 2, 3])
array2 = array1
array2[0] = 0 # array1也会跟着改变,就地操作
array2 = array2 * 2 # array2不会跟着改变,属于非就地操作,会创建一个新的地址给array2
array2 = array1[:]
array2 = array1.view()
array2 = array1.reshape((3, 1))
使用array.copy()
创建深拷贝以避免这种问题
非就地操作:会创建一个新的数组,并将其赋值给 array2(指向的地址发生改变)。在这种情况下,array2 将引用一个新的数组,原来的 array2 不再共享原始的内存。如下,都不会影响到array1:
array2 = -array1 # 有运算时不共享(会创建一个新的数组给array2)
array2[0] = 0 # array1不会跟着改变
array2 = array1 # 共享内存
array2 = array2 + 1 # array1不会改变(此时创建一个新的数组给array2)。但array2 += 1会影响array1,自增是就地(in-place)操作
array2 = array1
array2[0] = -array2[0] # 就地操作,1会改
array2[:] = -array2[:] # 就地操作,1会改
array2 = -array2 # 非就地操作,1不改
2、pytorch共享内存的情况:
和Numpy完全一样
tensor1 = torch.tensor([1, 2, 3])
tensor2 = tensor1
tensor2[0] = 0 # tensor1也会跟着改变
tensor2 = tensor1.view(-1)
tensor2 = tensor1.detach()
使用tensor.clone()
创建深拷贝以避免这种问题
3、Eigen中共享内存的情况:
Eigen::MatrixXd matrix1 = Eigen::MatrixXd::Random(3, 3);
Eigen::MatrixXd matrix2 = matrix1.block(0, 0, 2, 2);
Eigen::ArrayXd array1 = Eigen::ArrayXd::Random(5);
Eigen::ArrayXd array2 = array1.segment(1, 3);
直接进行赋值不会共享内存:
Eigen::VectorXd vector1 = Eigen::VectorXd::Random(5);
Eigen::VectorXd vector2 = vector1; // 不共享内存,vector2更改不影响vector1
4、List中共享内存的情况
Python当向列表中添加一个元素时,列表会存储对该元素的引用
a = np.array([1, 2, 3])
list_a = [a]
a[0] = 0 # list_a也会改变
C++中std::vector
不会有这种情况:
int main() {
Eigen::Vector3d A(0,0,0);
std::vector<Eigen::Vector3d> vector_A;
vector_A.push_back(A);
A(0) = 1; // vector_A不改
std::cout << vector_A[0].transpose() << std::endl;
return 0;
}
4、默认拷贝构造函数
C++是浅拷贝,如果有指针会有问题,但没指针的话没啥问题:
#include <iostream>
class MyClass {
public:
int value;
MyClass(int v) : value(v) {}
};
int main() {
MyClass A(5);
MyClass B = A;
B.value = 10;
std::cout << "修改后的 A 的值:" << A.value << std::endl; // 输出 5
std::cout << "修改后的 B 的值:" << B.value << std::endl; // 输出 10
return 0;
}
Python当将一个对象赋值给另一个对象时,实际上是创建了对同一个对象的引用
import numpy as np
class MyClass:
def __init__(self, num):
self.int = num
A = MyClass(1)
B = A
B.int = 10 # A也会被改
print(id(A))
print(id(B)) # 地址是一样的!
print("A.array:", A.int)
print("B.array:", B.int)
5、Python函数的传址和传值
不可变对象(如数字、字符串、元组):
当你传递不可变对象给函数时,函数内部对参数的任何修改都不会影响原始对象,类似于值传递的行为。
可变对象(如列表、字典、集合、np.array、torch.tensor):
当你传递可变对象给函数时,函数内部对参数的修改会影响原始对象,类似于引用传递的行为。
import numpy as np
import torch
def modify_immutable(x):
x = 100
def modify_mutable(lst):
lst.append(4)
def modify_array(arr):
arr[0] = 100
def modify_tensor(tensor):
tensor[0] = 100
a = 3
print("函数调用前的值:", a)
modify_immutable(a)
print("函数调用后的值:", a) # 不会改变
lst = [1, 2, 3]
print("函数调用前的列表:", lst)
modify_mutable(lst)
print("函数调用后的列表:", lst) # 会改变
original_array = np.array([1, 2, 3, 4, 5])
print("调用函数前的原始数组:", original_array)
modify_array(original_array)
print("调用函数后的原始数组:", original_array) # 会改变
original_tensor = torch.tensor([1, 2, 3, 4, 5])
print("调用函数前的原始 Tensor:", original_tensor)
modify_tensor(original_tensor)
print("调用函数后的原始 Tensor:", original_tensor) # 会改变
6、std::vector<>访问溢出时不会报错,只是会返回垃圾值
RPG代码访问相机类型和个数时,ID错了,但访问却没出错,导致一直没注意他的bug
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Python和C++赋值共享内存、Python函数传址传值、一些其他的遇到的bug
发表评论 取消回复