很简单,您可以通过提供具体实例将指针转换为引用,即取消引用:
void f(int& i);
f(*(new int)); // do not do this!
问题在于 C++ 中的原始指针正是如此——它们没有自动生命周期范围,并且通过转换为左值引用,您建议了一个实例是具体的并且不应被接收者销毁的协定。
int* ptr = new int;
f(ptr);
delete ptr; // otherwise it leaked
现代 C++ 使用 RAII 提供受控的自动生命周期管理,C++11 引入了unique_ptr 和shared_ptr 来处理指针。在 C++14 中,我们还拥有完全避免原始指针的机制。
std::unique_ptr<int> ptr = std::make_unique<int>(/* ctor arguments here */);
f(ptr.get());
// now when ptr goes out of scope, deletion happens automatically.
另见http://en.cppreference.com/w/cpp/memory/unique_ptr
在任何时候,只有一个std::unique_ptr 应该具有给定分配的地址(如果不是released,它将假定所有权并将delete 分配在退出范围内)。
对于引用计数指针:http://en.cppreference.com/w/cpp/memory/shared_ptr
--- 编辑 ---
基于 OPs cmets:
首先要注意
Pair p = { "one", "two" };
// and
Pair p("one", "two");
Pair p{"one", "two"};
是同义词,在所有情况下,它们通过分配堆栈空间并调用 Pair::Pair("one", "two") 以在那里构造 Pair 对象来创建堆栈局部变量 p。
但是请记住,这是一个堆栈变量 - 它具有自动生命周期,并且将在当前范围结束时到期。
{ Pair p{"one", "two"}; list_add(list, p); } //p is destroyed
理论上,您可以将其替换为
list_add(list, Pair{"one", "two"});
但重要的是list_add 是否希望 您 保留对象,直到您将其从列表中删除...这通常是基于列表的函数需要指针所期望的.如果它需要一个非常量引用,它可能会这样做。
回答你原来的帖子::
struct A { virtual void doSomething() {} };
struct B : public A { virtual void doSomething() override() {} };
void useDoSomethingInterface(A& a) {
a.doSomething();
}
int main() {
A a;
B b;
useDoSomethingInterface(a);
useDoSomethingInterface(b);
}
考虑以下几点:
void list_add(IList& list, Pair& pair) {
pair.next = list.head;
list.head = &pair; // << BAD NEWS
}
void badness(IList& list) {
list_add(list, Pair("hello", "world"));
}
void caller() {
IList list;
badness(list);
// list.head now points to a destroyed variable on the stack
C++ 中的 C 指针是原始的机器级指针。他们不参考计数。并且 C++ 对象实例具有固定的、定义良好的生命周期:直到作用域结束。
但是,如果 list_add 按值获取数据
void list_add(IList& list, Pair pair)
那我们就没事了。我们创建的临时 Pair 必须复制一次以创建 pair,然后再次复制到列表中,这很可惜,但至少不会崩溃。