C ++通过引用返回

时间:2010-04-05 19:48:45

标签: c++ reference

说,我有一个返回引用的函数,我想确保调用者只将它作为引用获取,并且不应该将其作为副本接收。 这在C ++中是否可行?

为了更清楚。我有这样的课程。

class A
{
private:
    std::vector<int>  m_value;
    A(A& a){ m_value = a.m_value; }

public:
    A() {}
    std::vector<int>& get_value() { return m_value; }
};

int main()
{
    A a;
    std::vector<int> x = a.get_value();
    x.push_back(-1);
    std::vector<int>& y = a.get_value();
    std::cout << y.size();

    return 0;
}

谢谢, 戈库尔。

5 个答案:

答案 0 :(得分:13)

通过使类不可复制,您可以为自己的类执行所需的操作。

通过将复制构造函数和operator =作为私有或受保护的成员,可以使类不可复制。

class C
{
private:
  C(const C& other); 
  const C& operator=(const C&);

};

有一个很好的例子,可以在这里制作一个NonCopyable class,你可以从你自己的类型派生出来。

如果您正在使用提升,您还可以使用boost::noncopyable

替代解决方案:

另一个解决方案是使用void返回类型并使调用者通过引用传递其变量。这样,当您获得对调用者对象的引用时,不会进行任何复制。

答案 1 :(得分:3)

如果您的函数返回对不应该复制的对象的引用,那么您的函数已经完成了所做的操作以防止复制。如果其他人调用您的函数并复制返回值,则

  1. 这是调用者所做的 错误 ,因为对象永远不应该被复制(在这种情况下,返回类型可能不应该有首先是可复制的),或
  2. 调用者的 无关 ,因为该函数一周只调用一次 (在这种情况下,您不得尝试削弱你的来电者代码)或
  3. 在调用者一侧是一个非常 哑的疏忽 (在这种情况下,错误将通过 profiling 找到)。
  4. 对于#1,要么你返回有自己的类型,要么你可以用你自己的类型包装你的回报。请注意,#2和#3之间的唯一区别是相关性 - 如果相关, 分析 将找到它。

    IMO当你需要的是一个引用时,你不应该通过返回一个指针来削弱你的代码。有经验的程序员,看到指针,会立即询问他们是否需要检查NULL返回值,是否动态分配对象,如果是,谁负责清理它。

    如果不能消除复制的可能性,你也不应该盲目地禁止复制你返回的任何内容。

    最后,这是旧的座右铭,C ++继承自C:相信你的用户知道他们在做什么。

答案 2 :(得分:1)

它“取决于”。是的,您可以隐藏复制构造函数(和赋值运算符),并且您的对象变为不可复制:

struct foo
{
private:
    foo(const foo&); // dont define
    foo& operator=(const foo&); // dont define
}:

但是如果你想知道一个特定的功能(即通常是可复制的,但不是这个功能),没有。事实上,你怎么能对呼叫者做些什么呢?

const foo& f = get_foo(); // okay, by reference, but...

foo f2 = foo(foo(foo(foo(foo(foo(f)))))); // :[

如果您的来电者想要做某事,那么您无法阻止它。

答案 3 :(得分:1)

在C ++ 11中,您可以通过删除复制构造函数来阻止复制构造函数:

class A{
    public:
    A(const A&) = delete;
}

答案 4 :(得分:0)

您是否正在尝试防止导致大型物体被意外复制的常见错字?如果是这样,您可以通过指针返回。离开&非常简单,但从指针复制对象需要花费一些精力。 OTOH,结果代码会更加丑陋,所以由你来决定它是否值得。