【问题标题】:c++ assigning only part of struct returned by function callc ++仅分配函数调用返回的结构的一部分
【发布时间】:2015-08-12 08:07:17
【问题描述】:

我有以下结构:

struct foo{
    int a[4];
    int b[4];
}

我有以下功能:

foo get_foo()
{
    foo ret_val;
    <..some assignments here..>
    return ret_val;
}

现在,我的主要代码:

void* process_a()
{
    int* pa = get_foo().a;
    <..do smth with "pa"..>
     return pa;
 }

看起来代码运行良好,但完全不知道完整结构会发生什么,因为我只能访问它的子部分。 还有,问题:

  • 是否可以仅将堆栈上创建的结构的一部分分配给指针?
  • foo 结构在哪里?在堆栈上?还是堆?
  • 编译器是否足够聪明,只能分配 int[4](这不太可能)还是会分配完整的 foo
  • 我的爸爸的寿命是多少?我可以在 process_a() 函数之外可靠地使用该指针吗?

谢谢! 伊戈尔。

【问题讨论】:

  • 你甚至不能在process_a 中使用pa,因为它没有指向任何有意义的地方。
  • 你不能使用 pa 甚至 inside process_a 函数,因为一旦表达式 pa = get_foo().a 完成,返回的结构就会被破坏,留下一个流浪者指针。如果您需要a,您应该复制它。请记住:如果您只使用正确的 C++ 类(例如 std::array 在您的情况下),处理这样的事情会容易得多。

标签: c++ struct heap-memory assign stack-memory


【解决方案1】:
  • 是的,但它仅在结构的生命周期内有效。
  • 从函数返回的结构是一个临时对象,它会立即被销毁。
    将有一些空间,可能是“在堆栈上”,供函数返回其结果。
    一旦分配的右侧执行完毕,结构就不会存储在任何地方,因为它不存在。
  • 它几乎肯定会为整个结构分配空间。
  • pa 的生命周期是 process_a 的主体,但如上所述,*pa 的生命周期已过期。
    因此,您不能将pa 的值用于任何内容(除了复制它),即使是内部 process_a

您的代码似乎运行良好,因为“似乎运行良好”是未定义行为的一种有效形式,就像任何其他事情一样。

【讨论】:

    【解决方案2】:
    • 是的,可以将指针分配给结构的内部字段。
    • foo 在堆栈中
    • 就像你说的 - 这不太可能
    • pa 的生命周期就像任何局部变量一样 - 直到函数结束。您不能在 func 范围之外使用它。但是,这里有一个不同的问题 - get_foo 的返回值是临时的,一旦超出分配给pa 的范围,它就可以被释放,因此之后pa 指向的数据的任何使用都会导致在未定义的行为中。

    【讨论】:

    • 第一点很好如果结构在堆栈上,但它不是。 get_foo 返回的结构没有存储在任何地方,因此它是临时的,将在表达式的末尾不再存在。
    • @JoachimPileborg 好吧,返回值必须存储在某个地方,至少直到表达式结束。据我所知,返回值的标准位置是堆栈。其实看这里:stackoverflow.com/questions/9109831/…
    • 也许编译器会将它存储在堆栈中,也许它会以某种方式对其进行优化,没有办法知道。我们确实知道的是,临时对象在赋值后被破坏并且不再有效。存储任何类型的指向被破坏对象或其成员的指针都会导致灾难和未定义行为。
    • @JoachimPileborg 对此没有争议,我在第四个项目符号中明确提到了它。但是我的第一个项目符号处理将指针分配给返回值的内部字段的有效性。分配本身是完全有效的。之后它会立即变成一个悬空指针,但这是一个完全不同的问题
    猜你喜欢
    • 1970-01-01
    • 2017-04-23
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 1970-01-01
    相关资源
    最近更新 更多