[英]Define object and pass by reference inside function parameter
假设我们有一个名为foo
的 function,它获取指向某个 object 的指针。
void foo(int *i){
// Some code
}
我们可以通过以下方式调用这个 function:
int i;
foo(&i);
有没有办法我们可以在 c++ 的一行中制作上述代码片段? 就像是
foo(&int(4)) // This is invalid.
两个限制:
foo
更改为按引用接收不是一种选择。foo(new int(4))
这样可能导致 memory 泄漏的东西。 “在一行中完成所有工作”通常是不可取的,因为它不会使代码更干净或更具可读性。 如果您必须声明一个int
并获取其地址,那么您的代码会更好地明确表达这一点。
但是,封装常见任务的常用方法是函数:
void foo_wrapper() {
int i = 0;
foo(&i);
}
然后调用foo_wrapper()
而不是foo(&i)
。
PS:房间里的大象是: foo
显然将参数用作外参数,但您想忽略它。 如果这真的是foo
应该使用的方式,那么它会做不必要的工作。 编写包装器隐藏了一个缺陷。 要解决实际问题foo
必须进行修改。 我知道你说它是第三方库代码,但与其为库代码编写变通办法,我会重新考虑(a)它是否是正确的库,或者(b)也许我确实误解了它应该如何使用。
我不知道为什么需要这种行为,并假设这是某种“脑筋急转弯”问题。 如果这是“宏观魔术”的练习,可能会有更好的解决方案。
这是有效的:
#include <iostream>
#include <memory>
void f(int *x){
++(*x);
std::cout << *x << '\n';
}
int main() {
f(std::make_unique<int>(4).get());
return 0;
}
预期 Output: 5
临时 object (类型为std::unique<int>
)将在 function 调用之后被清理。 没有 memory 泄漏,但动态分配当然有开销。
&
和std::addressof
被明确指定为不允许这样做,但如果你想忽略该安全措施,你可以定义你自己的std::addressof
包装器,这将允许它:
template<typename T>
constexpr auto myaddressof(T&& t) noexcept {
return std::addressof(t);
}
//...
// temporary created from argument to `addressof` lives
// until end of full-expression
foo(myaddressof(4));
不过这很容易出错。 例如,如果您将T&&
替换为T
,那么使用它可能会导致未定义的行为。 这依赖于可能不直观的临时生命周期规则。 我真的不认为这比声明变量并将其与块中的调用一起包装更好。
完整的演示基于@JasonLiam的评论。
(请注意,您可能不应该使用addressof
作为此 function 的名称。在某些极端情况下,如果调用不合格,依赖于参数的查找会导致该名称出现问题。)
void foo(int *i)
表示参数的生命周期由调用者在foo
之外管理。 这意味着在foo
调用之前分配一些时间并在foo
返回之后释放一些时间。 因此,由于您的原因#2,因此不可能有一个班轮。
处理可选指针值的惯用方式是使用nullptr
或NULL
(C++11 之前)参数作为忽略它的指示符: foo(nullptr)
。
您可以使用包装器 class (在某种程度上类似于myaddressof
function 模板的其他答案):
#include <iostream>
template<typename T>
class my_wrapper_class
{
public:
my_wrapper_class(T const &v) : value(v)
{
}
T *operator&()
{
return(&value);
}
T const *operator&() const
{
return(&value);
}
private:
T value;
};
void f(int *v)
{
std::cout << "v: " << *v << std::endl;
(*v)++;
}
int main()
{
f(&my_wrapper_class<int>(4));
return(0);
}
请注意,我读过的每本关于 C++ 的书都强烈建议不要重载一元运算符&
我刚刚做过。 另一个选项(未显示)是将转换运算符定义为适当的指针并在调用站点省略显式&
在我看来这同样令人困惑。
把它放在这里,以便有需要的人可以使用它并带有强烈的免责声明——不要那样做。 在朝这个方向前进之前,请考虑一下其他人在这个主题上的文章。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.