在c ++ 11中将指针传递给临时?

时间:2017-11-23 14:51:06

标签: c++ c++11 c++14 c++17 temporary-objects

我有一个现有的功能:

void foo(const Key* key = nullptr)
{
  // uses the key
}

我想将它指向临时Key对象(即rvalue),如:

foo(&Key());

这会导致编译错误,但是在c ++ 11/14中有一种方法可以做到这一点吗?我当然可以这样做:

Key key;
foo(&key);

但我不需要对象Key,我只需要它在foo()和foo()

或者我能做到:

foo(new Key());

但是这个对象不会被删除。

7 个答案:

答案 0 :(得分:6)

我不认为这是一个好主意,但如果你真的想要一个临时的而且无法改变foo,你可以将临时转换为const&

int main()
{
    foo(&static_cast<const Key&>(Key{}));
}

live example on wandbox

或者,你可以&#34;隐藏&#34;在方便功能背后创建对象:

template <typename T, typename F, typename... Ts>
void invoke_with_temporary(F&& f, Ts&&... xs)
{
    T obj{std::forward<Ts>(xs)...};
    f(&obj);
}

int main()
{
    invoke_with_temporary<Key>(&foo);
}

live example on wandbox.org

另一种选择:提供引用的foo重载:

void foo(Key&& key)
{
    foo(&key);
}

答案 1 :(得分:3)

自己控制一次丢弃变量的范围:

{
    Key key;
    foo(&key);
} // <-- 'key' is destroyed here

答案 2 :(得分:2)

获取指针而不是引用的唯一原因是指针是否为空。如果是这种情况,那么您的foo函数将如下所示:

void foo(const Key *key)
{
  if(key)
    //Do stuff with `key`
  else
    //Alternate code
}

考虑到这一点,你想要的是第二次重载,重构所有的&#34;做关键&#34;进入自己的功能,需要参考。那样做:

void foo(const Key &key)
{
  //Do stuff with `key`
}

void foo(const Key *key)
{
  if(key)
    foo(*key);
  else
    //Alternate code.
}

如果您在两种情况下都执行了公共代码,请将其重构为自己的函数。

是的,&#34;做关键&#34;很复杂,分成几行。但这表明这里有一个非常奇怪的设计。

你也可以用另一种方式重构它:

void foo(const Key &key) {foo(&key);}

答案 3 :(得分:1)

如果您关心的是可变范围(正如您在评论中提到的那样),您可以使用

loadUser(){ this.http.get('assets/json/collection.json') .map(res => res.json()) .subscribe(data => { this.data = data.results; console.log(data.results); }); } <div *ngFor="let result of results"> <p>{{results.title}}</p> </div>

答案 4 :(得分:1)

这是一个实用功能。它基本上是std::move 1

的倒数
template<class T>
T& as_lvalue( T&& t ) { return t; }

如果使用错误,可能导致悬空参考。

然后您的代码变为:

foo(&as_lvalue(Key()));

“无法获取临时地址”的目标是因为您可能会因隐式临时创建等原因而获得极其意外的行为。

在这种情况下,我们明确地采用临时的地址。

创建命名值,调用函数,然后立即丢弃命名值并不危险。

1 std::move取一个l或r值并返回一个rvalue引用,表明消费者应将其视为临时存在,其存在将很快被丢弃。 as_lvalue接受l或r值引用并返回一个左值引用,指示消费者应将其视为非临时值,其存在将持续存在。

它们都是有效的操作,但std::move更为重要。 (std::move可以称为as_rvalue。我建议不要使用像unmove这样聪明的名字。

答案 5 :(得分:-1)

  

在c ++ 11中将指针传递给临时?

不,你不应该。无法更改API?重写它。任何为你提供任何黑客攻击的人都会让你陷入一种非常危险的境地。

答案 6 :(得分:-2)

  

或者我能做到:

foo(new Key());
     

但是这个对象不会被删除。

你可以创建一个智能指针,但我不想。它仍然是一种可能性。

#include <memory>
foo(std::make_unique<const Key>().get());