打印引用返回的对象意外地不会产生垃圾

printf-ing an object returned by reference unexpectedly doesn't produce garbage

作为练习,我正在编写一个类似于 std::lock_guard<> 的 class,它包含一个 class T。我添加了一个 data 方法,该方法 returns 通过引用包装的东西。

我用一个包装整数对其进行了测试,并尝试将整数传递给 printf("%d\n, ..."),在某种程度上绕过了类型系统。由于宽度问题、崩溃或其他原因,我希望看到垃圾、指针或指针的前半部分。

令我惊讶的是,代码按预期工作......这表明我的引用返回模型是错误的......或者这里存在未定义的行为,代码恰好可以工作但没有保证。

在将按引用返回的事物传递给 printf 这样的 C 风格可变参数函数时,是否可以将其视为实际事物的实例?

这是代码的精简版本,仅包含相关方法和字段。

#include <cstdio>

struct int_holder {
public:
    int m_data{27};
public:
    int& data() {
        return this->m_data;
    }
};

int main() {
    int_holder h{};
    printf("%d\n", h.data());
}

我在 Windows 10.

上使用 MinGW 对其进行了测试
$ g++ -Wall -Werror -pedantic -std=c++11 .\return_int_by_ref.cpp
$ .\a.exe
27

printf() 不通过引用获取任何参数,仅通过值获取。因此,即使 data() returns 一个 int& 引用,将该引用传递给 printf() 也会传递 [=15] 的 value =] 被引用,而不是引用本身。 %d 需要一个 int 值,所以一切都很好,没有输出垃圾。

这不是未定义的行为。这就是 假设 传递对按值传递参数的引用的方式,它是非常明确的行为。它本质上是这样做的:

int &ref = h.data();
int value = ref;
printf("%d\n", value);