c++ - 如何保持在堆栈上分配的对象的动态类型?

标签 c++ c++11

假设我有:

class A { };
class B : public A { };
A f() { 
    if (Sunday())
        return A;
    else
        return B;
}

显然,自 A 以来,这不起作用的复制构造函数将被调用。有没有办法在不丢失其类型的情况下返回堆栈分配的对象?

我试过使用 std::shared_ptr<A>但它让我陷入了另一个问题 std::shared_ptr<B>不是 std::shared_ptr<A> .

最佳答案

不可能立即从创建对象的函数中返回堆栈分配的(即本地)对象。局部对象在函数返回时被销毁。您可以使用各种“智能指针”和类似技术隐藏/混淆对象分配的实际性质,但对象本身应该动态分配。

除此之外,只要遵守本地对象生命周期规则,本地对象的多态性与其他任何对象的工作方式完全相同。只需使用指针或引用

A a;
B b;

A *p = Sunday() ? &a : &b;
// Here `*p` is a polymorphic object
只要本地对象存在,上例中的

指针 p 就保持有效,这意味着您不能从函数返回 p

此外,正如您在上面的示例中看到的,它无条件地预先创建两个 对象,然后选择两者之一,同时不使用第二个。这不是很优雅。您不能在 if 语句的不同分支中创建此类对象的不同版本,原因与您不能以多态方式从函数返回本地对象的原因相同:一旦创建对象的本地 block 完成,对象被销毁。

后一个问题可以通过使用原始缓冲区和手动就地构造来解决

alignas(A) alignas(B) char object_buffer[1024]; 
// Assume it's big enough for A and B

A *p = Sunday() ? new(buffer) A() : new (buffer) B();
// Here `*p` is a polymorphic object
p->~A(); // Virtual destructor is required here

但它看起来并不漂亮。一种类似的技术(涉及缓冲区的复制)可能用于使本地多态对象在 block 边界中幸存下来(请参阅@Dietmar Kühl 的回答)。

因此,再次强调,如果您只想创建两个对象中的一个对象并让您的对象在 block 边界中存活下来,那么立即解决方案将本地对象放在一边是不可能的。您将不得不使用动态分配的对象。

关于c++ - 如何保持在堆栈上分配的对象的动态类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25474742/

相关文章:

c++ - 哪些库对 std::make_shared 使用了 "We Know Where You Live"优化?

c++ - 线程上下文的静态存储对象优化

c++ - valgrind 中函数指针的读取大小无效

c++ - clang 和 gcc 中的 Constexpr 复合赋值运算符

c++ - 无法将新行添加到 Gtk::ListBox

c++ - 通过接受关闭在另一个线程中使用的套接字的风险是什么?

c++11 如何插入简单的内存屏障?

java - 方法的 jni 签名

c++ - 如果显式定义了构造函数,是否必须初始化类成员?

c++ - 将多个元素插入二维 block