透化多态对象

时间:2018-10-16 09:23:07

标签: c++

请考虑以下代码段:

Map<Integer, List<Loan>> loansByDuration = loans.stream()
        .collect(groupingBy(Loan::getDuration, LinkedHashMap::new, toList()));

List<Loan> previousGroup = null;
for (List<Loan> currentGroup : loansByDuration.values()) {
    if (previousGroup != null) {
        currentGroup.addAll(previousGroup);
    }
    previousGroup = currentGroup;
}

我有一个关于#include <new> #include <iostream> struct IDivideResult { virtual int result() = 0; virtual int remainder() = 0; }; struct DivideResult : IDivideResult { DivideResult(int result, int remainder) : result_(result), remainder_(remainder) {} int result() override { return result_; } int remainder() override { return remainder_; } int result_, remainder_; }; struct LazyDivideResult : IDivideResult { LazyDivideResult(int dividend, int divisor) : dividend_(dividend), divisor_(divisor) {} int result() override { return Transmogrify()->result(); } int remainder() override { return Transmogrify()->remainder(); } DivideResult *Transmogrify() { int result = dividend_ / divisor_; int remainder = dividend_ % divisor_; return new (this) DivideResult(result, remainder); } int dividend_, divisor_; }; void Print(IDivideResult *div) { int result = div->result(); int remainder = div->remainder(); std::cout << result << " " << remainder << "\n"; } int main() { IDivideResult *div = new LazyDivideResult(10, 3); Print(div); } 函数行为的问题。

预期的行为:调用Print的div指向result()类的实例后,调用DivideResult函数将调用remainder()函数。

可能(?)的行为:在调用DivideResult::remainder()指向result()的指针时 vtable中的缓存。对LazyDivideResult的下一次调用重用了先前缓存的指向remainder()的指针,因此调用了vtable

我听说虚拟表不是C ++标准的一部分。同样,对clang / gcc / msvc生成的代码进行反汇编也会产生预期的行为。

这里的问题是:是否允许编译器生成导致上述“可能的行为”的代码?有保证吗?

1 个答案:

答案 0 :(得分:1)

这是不确定的行为。

一旦调用20170630-4072-00,指针4072-00-20170630就会失效,因为您已经终止了它指向的对象的生命周期。您观察到的症状是它在调用div->result()时“成功”。

从理论上讲,一个实现可以假设您只将div传递给remainder,因为传递DivideResult就是UB。