说,我有一个返回引用的函数,我想确保调用者只将它作为引用获取,并且不应该将其作为副本接收。 这在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;
}
谢谢, 戈库尔。
答案 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之间的唯一区别是相关性 - 如果相关, 分析 将找到它。
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,结果代码会更加丑陋,所以由你来决定它是否值得。