在C ++中从指针转换为引用

时间:2017-09-23 21:49:41

标签: c++ pointers reference

我想使用new创建一个类的实例,但我想转换为引用以供使用指针以外的其他用法。目前我正在使用此行Foo& rf = *f;进行明确转换,看起来有点傻。有没有更好,更优雅的方法来创建引用变量并引用new创建的实例?

以下是一些显示我正在做的事情的代码,

class Foo{
    public:
    Foo(){

    }

    void printValue() {
        cout << "This is Foo object " << endl;
    }
};

int main() {
    Foo* f = new Foo();
    Foo& rf = *f;
    rf.printValue();
    f -> printValue();
}

4 个答案:

答案 0 :(得分:1)

你可以这样写:

Foo* foo = new Foo();
Foo& fooRef = *foo;

在一行中:

Foo& fooRef = *new Foo();

但是,请注意,您应该稍后删除已分配的内存:

delete &fooRef;

我不建议您以这种方式编写代码,以避免内存泄漏。查看this answer了解更多详情。尽可能选择智能指针或容器。

答案 1 :(得分:1)

  

...转换为参考以供使用指针以外的其他用途。

我更喜欢我的代码中的引用(并避免使用指针)。主要是因为nullptr可能具有特殊含义(引用不会)需要一些思考来确认,下次我查看代码时。

我的解决方案是新建大于自动内存的对象,以便在适当的生命周期内获得指针。然后,我使用解除引用的指针调用using方法或函数。这使得指针(在生命周期开始时,例如main)保持不变,以后仍可用于删除。

// bigData  used many places
void use1_of_Data (BigData_t& bigData, Small_t& sd) {
    //... do something with data
}

void use2_of_Data (BigData_t& bigData, Small_t& sd) {
    //... do something with data
}

//...
void use3_of_Data (BigData_t& bigData, Small_t& sd) {
    //... do something with data
}

int main(int argc, char* argv[]) 
{
   // ...
   BigData_t* bd = new BigDta_t; // (sizeof(BigData_t) > autovar space)
   Small_t    sd;
   {
      assert(nullptr != bd); 
      // note - bd lasts the lifetime of program

      use1_of_Data (*bd, sd);
      use2_of_Data (*bd, sd);
      //...
      use3_of_Data (*bd, sd);
   }
   // what's new'd in main, is deleted in main
   delete bd;        
}

答案 2 :(得分:0)

正如其他人所说,如果Foo实例的非堆内容不是很大,以至于Foo实例本身需要在堆上分配,那么最好只使用堆栈: / p>

Foo foo;
foo.printValue();

但是,如果由于某种原因确实需要在堆上进行分配,那么在普通指针中保持对它的唯一引用是危险的,因为如果任何代码抛出异常,它将会永远不会被解除分配。事实上,大多数现代C ++指南建议不要使用普通指针来拥有数据:

Foo * fooPtr = new Foo();
doSomething();  // If an exception is thrown here, the Foo never gets deallocated!
Foo& foo = *fooPtr;
foo.printValue(); // If printValue throws an exception, the Foo never gets deallocated!
delete foo;

如果您不熟悉这类问题,我建议使用Google搜索RAII(&#34;资源获取是初始化&#34;)这是了解用C ++编程时的一个重要概念。

在这种情况下实现RAII的一种简单方法是使用智能指针(std :: shared_ptr或std :: unique_ptr)。

额外的引用变量仍然有助于避免必须使用箭头操作符来调用smartpointer上的函数。我不同意其他一些不会在本地引用中绑定本地引用的问题的回答者。我更喜欢尽可能使用引用,因为当我使用引用时,我可以确定引用不是null(引用应该始终引用实际对象),而当我使用指针(甚至是智能指针)时我必须始终小心我的代码正确处理指针为空的情况。当指针初始化发生在指针的使用附近时,这可能不是什么大问题,但是当它们分开时,很难通过代码跟踪以确保指针不能为空。引用使这个自我记录。

我认为首先确保指针或智能指针值不能为空,然后将本地引用绑定到指向的值通常很有用,因为我可以自由地使用引用无需担心每次使用它是否为空的可能性:

std::unique_ptr<Foo> fooPtr = std::make_unique<Foo>(/* Foo constructor args go here */);
doSomething(); // Now if an exception thrown here, Foo gets deallocated.
Foo& foo = *fooPtr; // We know the pointer is not null here (it just
                    // got returned from make_unique which
                    // didn't throw a bad_alloc exception) so it's
                    // safe to bind a reference to it here.
                    // Also, this reference has lifetime less than the
                    // smart pointer, so will never outlive it.

// .. many lines of code later ..
foo.printValue(); // No need to worry about null here.
                  // If exception thrown here, the unwinding of the stack
                  // causes fooPtr to deallocate Foo.

// No need to call delete here.
// fooPtr will automatically deallocate Foo when it goes out of scope.

答案 3 :(得分:-1)

如果我们谈论优雅,我建议你使用shared_ptr吗?

#include <iostream>
#include <memory>

using namespace std;

class Foo{
    public:
    Foo(){

    }

    void printValue() {
        cout << "This is Foo object " << endl;
    }
};

int main(int argc, char *argv[])
{
    Foo* f = new Foo();
    std::shared_ptr<Foo> mySharedPtr(f);
    f->printValue();
    mySharedPtr.get()->printValue();

    return 0;
}