可以传递匿名变量的地址吗?
Possible to pass address of anonymous variable?
我一直使用匿名变量,当我不需要在整个当前范围内悬挂命名对象时。
我需要使用一个函数 - 在我的控制之外 - 它将指针作为参数并且不进行 NULL 检查。我希望能够传递匿名变量的地址(因为我不在乎在取消引用的地址写入的值),但遇到编译错误。下面的简化示例...
#include <iostream>
void ptrFunc( const int* p )
{
if ( p )
{
std::cout << "*p == " << *p << std::endl;
}
}
void refFunc( const int& i )
{
std::cout << "(ref)i == " << i << std::endl;
}
void valueFunc( int i )
{
std::cout << "i == " << i << std::endl;
}
int main( int argc, char* argv[] )
{
valueFunc( int() ); // This is fine.
refFunc( int() ); // This is also fine.
ptrFunc( &(int()) ); // This doesn't compile.
}
。生成此编译错误:
>g++ -g main.cpp
main.cpp: In function 'int main(int, char**)':
main.cpp:25:19: error: lvalue required as unary '&' operand
ptrFunc( &(int()) ); // This doesn't compile.
^
>g++ --version
g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
编译器错误非常可读:使用地址运算符需要左值。但我想知道社区是否可以帮助我理解这种限制背后的理由。在我看来,我尝试的使用可能是合理的,因为匿名变量的生存期取决于分号,即它在ptrFunc()
的生命周期内是"活着的"。
我考虑过允许指向匿名变量的指针是否被认为是"危险的",因为它们的寿命缩短了。但实际上,如果指针的任何用途 - 即使是对于左值或堆分配的对象也会遇到同样的问题:如果有人挂在任何指针上,它总是有指向无效内存的危险。指针的使用本质上取决于仔细的编码,我认为这个尝试的用例在这方面并没有特别的不同。
我很想知道这背后的理由。谢谢。
我还尝试过什么?
尝试使用在线gcc-4.9.2
编译示例代码以达到相同的效果;因此此问题不是过时编译器的限制/错误。
但我想知道社区是否可以帮助我理解这种限制背后的基本原理。在我看来,我尝试的使用可能是合法的,因为匿名变量的生命周期取决于分号,即它在
ptrFunc()
的生命周期中是"活着的"。
在这种情况下,是的,它会起作用。一般来说,没有。
引用会导致临时的生存期延长。指针没有。也就是说,给定:
int main() {
const int & a = 1;
int && b = 2;
const int * c = &static_cast<const int &>(3); // don't do this
return a + b - *c;
}
引用a
和b
继续引用有效对象。指针c
则没有,并且生存期延长规则无法在指针没有重大根本变化的情况下适用于指针。对于引用是可行的,因为引用是一个新的(与 C 相比)语言功能,并且作为一个新的语言功能,使它们不可变没有问题。指针有很多使用它们的现有代码,这些代码会因规则的更改而失效。
最终,您在此处要求的内容不存在,这是有充分理由的:带有地址的值必须位于某个位置,因此具有一定的范围/生存期。要传递给函数的指针是地址。它可以多次读取,当非常量时,可以写入。
编译器不知道调用函数将如何使用您的参数,并希望自由地放置右值,包括将它们折叠到代码中的常量中,或将它们放入寄存器中。你不能把一个地址传递给一个函数。
您所要求的内容似乎简化为编译器糖,它在堆栈上创建一个本地,获取对它的引用,并将其传递给函数,但从代码中隐藏其地址,以便没有其他代码可以使用该值。C++建立在显式内存管理之上,因此与此相反。
好的,但我真的很想这样做
不过,只是为了好玩,我认为您可以做这样的事情:
#include <memory>
#include <iostream>
void ptrFunc( const int* p )
{
if ( p )
{
std::cout << "*p == " << *p << std::endl;
}
}
int main()
{
ptrFunc(std::unique_ptr<int>(new int()).get());
return 0;
}
这是如何工作的?
糟糕的是,它的效率非常低。不过,从语法上讲,它可以执行您想要的操作:
ptrFunc( // 1. call ptrFunc
std::unique_ptr<int>( // 2. instantiate a unique_ptr as a temporary
// this takes a pointer to a heap-allocated value
// and assumes ownership of it. it deletes that
// value when it goes out of scope. for a
// temporary, this happens after the expression.
new int() // 3. heap-allocate an integer
).get() // 4. returns a raw-pointer to the heap-allocated
// value owned by the unique_ptr. That value
// becomes invalid memory if accessed after the
// unique_ptr destroys it.
);
> C++11 引入了获取变量地址std::addressof()
,即使它是覆盖operator&
的类类型。 您可以应用类似的技术来获取临时变量的地址,例如:
template <class T>
const T* addrtemp(const T& arg)
{
return reinterpret_cast<T*>(
&const_cast<char&>(
reinterpret_cast<const volatile char&>(arg)
)
);
}
ptrFunc( addrtemp(int()) );
演示
- 将数组的地址分配给变量并删除
- 将地址分配给本地指针后,公共对象的变量将消失
- 通过按地址访问变量
- 为什么未命名的结构内联变量在每个翻译单元中没有相同的地址?
- 为什么我可以将变量存储在不是其最小对齐方式的倍数的地址?
- 为什么同一个变量的内存地址不同?
- 从二进制流中读取时,将双精度变量的地址转换为 char* 意味着什么?
- 不同块作用域中的 C++ 变量具有相同的地址
- 循环中的变量被设置为下一个数组的元素始终具有相同的内存地址?
- C++在变量的内存地址上做什么来"deallocate"它?
- 如何在不为其声明变量的情况下获取和使用常量值的地址?
- 如何找到在本地范围内声明的变量的地址?
- 附加调试器并以编程方式获取变量地址 Visual Studio
- 初学者问题:C++指针/地址 - 和变量之后不是以前?
- 为什么我无法获取 MSVS2019 / C++ 中字符或uint8_t变量的内存地址?
- 为什么变量的打印地址在每次执行时都会打印随机值,即使它是 C 中的逻辑地址?
- 变量地址的运算符[]是如何工作的
- 使用基地址和偏移量获取变量的地址
- 两个不同的进程,在同一地址上有 2 个 std::atomic 变量?
- libmysql:警告:返回局部变量"行"的地址(C++/C)