如何将参数传递给构造函数?

时间:2010-07-08 07:43:43

标签: c++

我有一个A类,它由对象B和C组成。如何编写A的构造函数来获取B和C对象?我应该通过值,(const)引用还是指针传递它们?我应该在哪里解除分配?

我想到了指针,因为那时我可以写:

A a(new B(1,2,3,4,5), new C('x','y','z'))

但我不知道这是不是一个好习惯。有什么建议吗?

4 个答案:

答案 0 :(得分:7)

通常你传递const引用:

A a(B(1,2,3,4,5), C('x','y','z'))

这里不需要指针。

通常您存储值,除非复制效率太低。 然后,类定义为:

class A {
private:
    B b;
    C c;
public:
    A(const B& b, const C& c): b(b), c(c) { }
};

答案 1 :(得分:4)

  

我应该通过值,(const)引用还是指针传递它们?

  1. 如果对象很大则通过const引用
  2. 按对象小的值
  3. 如果它是一个可以为零的可选参数(即“NULL”),则使用const指针
  4. by pointer如果它是一个可选的参数,可以为零,但将由构造的类拥有(即解除分配)。
  5. 请注意,如果您的类具有B和C的内部实例,那么通过引用,值或const引用传递它们很可能涉及使用复制构造函数或赋值运算符。使用指针时没有必要。

      

    A a(新B(1,2,3,4,5),新C('x','y','z'))

    通常(即并非总是)这是一个坏主意,因为:

    1. 如果A没有释放参数,则会发生内存泄漏。
    2. 如果A获取参数的所有权并取消分配它们,那么您将无法将在堆栈上分配的值作为参数传递。尽管如此,根据您的代码设计,这可能是可以接受的(Qt 4经常使用 new 创建的对象的所有权)
    3.   

      我应该在哪里解除分配?

      最好的办法是确保编译器自动为您释放参数。 这意味着通过引用,const引用或值传递。或使用智能指针。

答案 2 :(得分:2)

您传递的内容取决于您的需求。

你需要一份你传递的东西的副本吗?然后通过const-reference传递。

struct A
{
    A(const B& b, const C& c) : m_b(b), m_c(c) {}

private:
    B m_b;
    C m_c;
};

并按照以下方式构建:

A myA(B(1,2,3), C(4,5,6));

如果您希望A对象引用其他BC个对象(但不拥有它们),请使用指针(或可能引用)。

答案 3 :(得分:1)

编辑:此处给出的示例不尊重三巨头的规则(感谢@Philipp!)。如果使用下面给出的A的定义,代码将在A的副本构造上崩溃,或者在A的分配上崩溃。为了正确定义代码,应该为A明确定义赋值运算符和复制构造函数(或明确禁止 - 声明为私有且从未实现过)。 (结束编辑

  

我应该按值传递它们吗?   (const)引用,还是指针?

如果A 使用 B和C,则通过A中的引用或指针保存它们。要在引用和指针之间进行选择,请参阅如何分配B和C.

如果它们是在与A相同的范围内构造的局部堆栈对象,则通过const引用传递它们

如果它们是A使用的动态分配对象,则使A 拥有它们:通过指针传递它们,并让A的析构函数删除它们。

如果它们是A的可选组件通过指针传递它们(可以为空)。

如果A不负责删除它们,请通过* const传递它们。

  

我应该在哪里解除分配?

通常在您不再需要它们的地方:)。

如果需要超出A的范围(如果它们是A使用的外部对象),则在A的范围完成时删除它们。

如果它们归A所有,则在析构函数中删除它们。如果指针应该更改,那么在A的生命周期内删除它们也是有意义的。

这是一个例子,其中B是注入A(由A拥有)的可替换组件,C是A拥有的可选组件(但也注入A)。

(“拥有”表示A负责删除这两个对象)

class B;
class C;

class A
{
    B* b;
    C* c;
public:
    A(B* const bb, C* const cc = 0) // cc is optional
    : b(bb), c(cc)
    {
    }

    void resetB(B* const bb = 0)
    {
        delete b;
        b = bb;
    }

    ~A()
    {
        resetB();
        delete c;
    }
};

{
    A a(new B, new C);
    a.resetB(); // delete B
    a.resetB(new B); // delete former B and set a new one
} // both members of A are deleted
  

但我不知道这是否好   练习与否。有什么建议吗?

这取决于你,但你可以像A a(B(1, 2, 4), C(1, 2, 3))那样简单地写A a(new B(1, 2, 4), new C(1,2,3));(在前一种情况下 - 没有新的那个 - A :: b和A :: c应该是引用或者类中的对象/值,A根本不应该删除它们。

问题不应该是如果你想用B和C的动态分配编写语句,但是如果你需要。动态分配很慢,如果您没有要求,则不应该这样做。