存储作为参数传递的引用的内容

时间:2015-01-16 01:47:11

标签: c++ qt

我用C ++ / Qt编程。这些代码片段是否通过复制正确保存了引用的内容?

使用初始化列表:

Foo(const Bar &bar) : bar(bar) { }
Bar bar; //member variable of Foo class

在Setter方法中:

void TestClass::setName(const QString &name) {
    this->name = name;
}
QString name; //member variable of TestClass class

如果是,请复制副本吗?:

void TestClass::setName(const QString name) {
    this->name = name;
}
QString name; //member variable of TestClass class

这是否会导致未定义的行为,因为引用的对象可能会在早期被解构?:

Foo(Bar &bar) : bar(bar) { }
Bar &bar; //member variable of Foo class

存储传递引用的内容是不好的样式?传递需要存储的参数的更好方法是什么?

1 个答案:

答案 0 :(得分:4)

复制开销

这两种方法都会将输入字符串中的数据复制到类变量中:

QString name; //member variable of TestClass class

void TestClass::setName1(const QString & name) {
    this->name = name;
}

void TestClass::setName2(const QString name) {
    this->name = name;
}

在第二个中,首先在堆栈上创建QString的副本。你认为pass-by-value会导致更多的拷贝开销是正确的。这就是因为包含大量数据的类通常不鼓励按值传递。

有关传递引用与传递值传递的更多讨论,请参阅this question

但是,在此特定示例中,开销的差异非常小:QString使用implicit sharing。复制QString时(例如使用operator =),它只是创建对同一数据的另一个引用。因此,复制QString - 即使是很长的QString - 也不比复制引用更加强烈。

悬空参考

Foo(Bar &bar) : bar(bar) { }
Bar &bar; //member variable of Foo class

如果在bar课程仍然存在的情况下删除原始Foo,此代码确实会导致问题(这被称为" dangling reference&#34 )。 以这种方式使用引用很像使用指针:作为程序员,您可以确保所有涉及的对象都能正确管理内存。

如果您担心Qt应用程序中的悬挂指针/引用,请尝试QPointer

  

保护指针QPointer的行为类似于普通的C ++指针T *,不同之处在于它在被引用的对象被销毁时自动设置为0(与正常的C ++指针不同,后者变为"悬挂指针" in这种情况)。 T必须是QObject的子类。

您可以像这样重写上面的代码:

Foo(Bar * bar) : bar(bar) { }
QPointer<Bar> bar; //member variable of Foo class

然后,您可以免受悬空指针错误的影响:

Bar * myBar = new Bar();
Foo myFoo(myBar);  // myFoo->bar is set to myBar
delete myBar;      // myFoo->bar becomes 0

只要您的类方法在使用之前检查this->bar为null,就可以避免在未初始化的内存上运行。 (或者,如果你不这样做,你很快就会得到一个分段错误,而不是通过访问已经删除的地址可能会有更微妙的未定义行为。)