打印引用返回的对象意外地不会产生垃圾
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);
作为练习,我正在编写一个类似于 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);