我正在一个拥有庞大遗留代码库的项目中工作,并且一直试图重新设计它的一部分以摆脱旧的C风格代码。
我遇到了问题并准备了一个简短的程序来解释。
我正在使用的遗留接口需要我将指向结果数据的指针传递为void *,我希望避免更改此内容。
示例中的unique_ptr只是用于演示,在我的实际代码库中,处理数据的所有内容都使用智能指针来管理内存。
我的问题是,结果数据被破坏了(参见上一个输出行/最后一次调用printPayload);最后一切都是0,但是转换到void *并且如第2和第3个输出线所示,它似乎没有问题。
这是与临时相关的问题吗? 我不明白......
我希望这种问题与你们中的一些人有关。
#include <iostream>
#include <memory>
struct Payload
{
long a;
int b;
int c;
Payload() : a(), b(), c() {}
Payload(long setA, int setB, int setC) : a(setA), b(setB), c(setC) {}
};
void printPayload(const Payload& printThis)
{
std::cout << "payload -- a: " << printThis.a << " b: " << printThis.b << " c: " << printThis.c << std::endl;
}
void doSomething(Payload* sourceData, void* targetData)
{
if (!sourceData) return;
std::unique_ptr<Payload> sourceDataUnique(sourceData);
sourceDataUnique->a = 222;
sourceDataUnique->b = 333;
sourceDataUnique->c = 444;
printPayload(*sourceDataUnique);
targetData = reinterpret_cast<void*>(sourceDataUnique.release());
printPayload(*(reinterpret_cast<Payload*>(targetData)));
}
int main(void)
{
Payload* myPayload = new Payload(14, 8, 1982);
Payload myResult;
printPayload(*myPayload);
doSomething(myPayload, &myResult);
printPayload(myResult);
}
输出:
payload -- a: 14 b: 8 c: 1982
payload -- a: 222 b: 333 c: 444
payload -- a: 222 b: 333 c: 444
payload -- a: 0 b: 0 c: 0
答案 0 :(得分:8)
targetData
是doSomething
的本地变量。为其分配地址后,它将超出范围。
您永远不会真正分配给myResult
。
答案 1 :(得分:3)
在您的代码中,参数targetData
是doSomething
函数的本地参数(即,退出函数范围后,任何更改都将丢失)。但是,*targetData
是指myResult
函数中声明的变量main
。
因此,以下代码应该有效:
void doSomething(Payload* sourceData, void* targetData)
{
if (!sourceData) return;
sourceData->a = 222;
sourceData->b = 333;
sourceData->c = 444;
printPayload(*sourceData);
Payload* td = static_cast<Payload*>(targetData);
*td = *sourceData;
printPayload(*td);
}
答案 2 :(得分:1)
您无法将源数据复制到目标,但只能更改targetData指针指向的对象。
这样的事情会起作用:
Payload* targetPayload = reinterpret_cast<Payload*>(targetData);
*targetPayload = *sourceData;
通过智能指针获取源有效负载的所有权可能是一个坏主意 - 如果编写调用代码以正确处理异常,那么它将在错误上删除对象,因此智能指针将意味着它被删除两次。如果没有编写调用代码来正确处理异常,那么编写无法抛出异常的代码是你的工作,而智能指针并没有帮助。
(因为它是指针之间的转换,你可以使用static_cast,但我更喜欢reinterpret_cast,因为void *可能是任何,reinterpret_cast告诉其他开发人员正在发生一些潜在的危险。)< / p>