作为练习,我正在编写类似于std::lock_guard<>
的类,其中包装了类T
。我添加了一个data
方法,该方法通过引用返回包装的东西。
我使用包装的整数对其进行了测试,并尝试将整数传递给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
答案 0 :(得分:4)
printf()
不会通过引用仅接受值的任何参数。因此,即使data()
返回一个int&
引用,将该引用传递给printf()
也会传递所引用的int
的 value ,而不是引用自己。并且%d
期望一个int
值,所以一切都很好,没有垃圾输出。
这不是未定义的行为。这是假定传递给值传递参数的引用的方式,这是非常定义的行为。本质上是这样做的:
int &ref = h.data();
int value = ref;
printf("%d\n", value);