用于放入在一组函数中传递的参数的结构

时间:2011-03-29 07:53:15

标签: c++ pointers parameters null scope

我需要能够灵活地更改传递给不同函数的参数,具体取决于调用函数的位置,所以我决定将所有参数放在struct中,但是大多数参数都是结构或者类本身,我希望可以选择将它们保留为NULL,所以我必须将指针传递给结构/类。

struct A
{
    otherB* b;  // NULL should be a valid value
    otherC* c;
};

但是我现在的问题是,围绕这些指针传递A将是唯一被复制的东西,所以如果我做了以下就会出现问题吧?

void func(A& a) //non const cause I wanna change contents of A.
{
   a.b = new b();
}

A myA;
otherC somec; // all these are currently automatic variables in my pgm.
myA.c = &somec;

func(myA);  //myA goes out of scope? so I've lost all pointers assigned and since somec is out of scope too, I have a problem?

解决类似问题的最佳方法是什么+我希望能够灵活地将NULL传递给我的任何参数,但不确定是否在任何地方使用原始指针都是个好主意?

5 个答案:

答案 0 :(得分:4)

要解决资源管理问题,您应该使用boost::shared_ptr(或C ++ 0x中的std::shared_ptr)。

struct A
{
    boost::shared_ptr< otherB > b;
    boost::shared_ptr< otherC > c;
};

void func(A& a)
{
   a.b = boost::make_shared< otherB >();
}

A myA;
otherC somec;
myA.c = boost::shared_ptr< otherC >(&somec, null_deleter());

func(myA);

myA超出范围时,将自动释放所有资源。由于somec已在堆栈上分配,因此我们将其封装在使用shared_ptr的{​​{1}}中,如下所示:

null_deleter

这将删除对象,它将什么都不做(这正是我们想要的堆栈分配对象)。但请注意,您必须确保struct null_deleter { void operator()(void *) { } }; 的有效期超过somec,否则您将违反访问权限。

答案 1 :(得分:1)

boost::optional<>允许您测试字段是否已设置。

简单的例子(不会编译,我甚至没有对它进行远程测试,理论上它应该是如何工作的)

struct params
{
  boost::optional<int> a;
  boost::optional<foo> b;
  boost::optional<bar> c;
};

void func(params& p)
{
  if (p.a)
  {
    // do stuff with a
  }
  if (p.b)
  {
    // do stuff with b
  }
  if (p.c)
  { 
    // do stuff with c
  }
  else
    p.c = bar(); // again copy constructed and now initialized...
}

params p;
p.a = 1;
p.b = foo(); // copy constructed, however you can store a reference in the optional too.
// c is uninitialized

func(p);

// when p goes out of scope, everything is gone..

答案 2 :(得分:0)

您基本上必须分析所有权,即一旦不再使用对象,谁可以分配以及谁负责删除对象。

重要的是要记住,如果你混合动态分配的东西和放在堆栈上的东西,你就不能对它们应用delete,因为它不可能删除堆栈上的东西。

一种方法可能是只使用new并在A中定义一个删除所有指针的析构函数。另一种方法可能是您将注册以后应删除的对象的位置。或者您可以使用现有的引用计数工具,如其他答案所示。

答案 3 :(得分:0)

不,您对myAsomec范围的看法是错误的。你现在拥有的东西没有任何问题 - 尽管我个人认为引用对于指针来说是一个更好的选择。

void func(A& a) //non const cause I wanna change contents of A.
{
    a.b = new b();
}


int main() {
    A myA;
    otherC somec; // all these are currently automatic variables in my pgm.
    myA.c = &somec;

    func(myA);
    // myA and somec are still perfectly in scope to be saved, or deleted, or w/e as you like
}

答案 4 :(得分:0)

从您的描述中不清楚,但如果您遇到问题 因为somec超出了范围,所以它只能是因为func 保存指针的副本。不要这样做:在功能,复制对象, 不是指针。

PS:如果大多数时候大多数指针都是空的,你应该这样做 考虑使用类似下面的句法糖:

struct A
{
    //  pointer members...
    A() : // ... set all pointers to null...
    A& withB( B const& someB ) { otherB = &someB; return *this ; }
    A& withC( C const& someC ) { otherC = &someC; return *this ; }
    //  And so on for all of the rest of the pointers.
};

func( A().withC( somec ) );

不知道它是否适合您的情况,但通常是这样 方便。