Nic*_*ton 325 c++ reference c++-faq
我觉得这有点主观; 我不确定这个意见是否会一致(我已经看过很多代码片段,其中返回了引用).
根据对这个问题的评论我刚刚问过,关于初始化引用,返回引用可能是邪恶的,因为,[据我所知]它更容易错过删除它,这可能导致内存泄漏.
这让我很担心,因为我跟随了一些例子(除非我想象的事情)并且在相当多的地方做到了这一点......我误解了吗?这是邪恶的吗?如果是这样,那有多邪恶?
我觉得因为我的指针和引用混合在一起,再加上我是C++的新手,以及对什么时候使用的完全混淆,我的应用程序必须是内存泄漏地狱......
另外,我知道使用智能/共享指针通常被认为是避免内存泄漏的最佳方法.
GMa*_*ckG 395
通常,返回引用是完全正常的并且始终发生.
如果你的意思是:
int& getInt() {
int i;
return i; // DON'T DO THIS.
}
Run Code Online (Sandbox Code Playgroud)
这就是种种邪恶.分配的堆栈i将消失,你指的是什么.这也是邪恶的:
int& getInt() {
int* i = new int;
return *i; // DON'T DO THIS.
}
Run Code Online (Sandbox Code Playgroud)
因为现在客户端最终必须做到这一点:
int& myInt = getInt(); // note the &, we cannot lose this reference!
delete &myInt; // must delete...totally weird and evil
int oops = getInt();
delete &oops; // undefined behavior, we're wrongly deleting a copy, not the original
Run Code Online (Sandbox Code Playgroud)
请注意,右值引用仍然只是引用,因此所有恶意应用程序保持不变.
如果要分配超出函数范围的内容,请使用智能指针(或通常是容器):
std::unique_ptr<int> getInt() {
return std::make_unique<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
现在客户端存储一个智能指针:
std::unique_ptr<int> x = getInt();
Run Code Online (Sandbox Code Playgroud)
参考也可以访问您知道生命周期在更高级别保持打开的内容,例如:
struct immutableint {
immutableint(int i) : i_(i) {}
const int& get() const { return i_; }
private:
int i_;
};
Run Code Online (Sandbox Code Playgroud)
在这里我们知道可以返回一个引用,i_因为无论调用我们管理类实例的生命周期,所以i_至少会存活那么久.
当然,只是:没有错:
int getInt() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果生命周期应该留给调用者,而你只是计算值.
简介:如果对象的生命周期不会在调用后结束,则可以返回引用.
Cha*_*tin 63
不,不,一千次没有.
什么是邪恶的是引用动态分配的对象并丢失原始指针.当您new成为对象时,您有义务获得保证delete.
但是看看,例如operator<<:必须返回引用,或者
cout << "foo" << "bar" << "bletch" << endl ;
Run Code Online (Sandbox Code Playgroud)
不行.
Dav*_*ley 46
您应该返回对不会立即消失的现有对象的引用,以及您不打算进行任何所有权转移的对象.
永远不要返回对局部变量或类似变量的引用,因为它不会被引用.
您可以返回对函数独立的引用,您不希望调用函数负责删除.这是典型operator[]功能的情况.
如果要创建某些内容,则应返回值或指针(常规或智能).您可以自由地返回一个值,因为它将进入调用函数中的变量或表达式.永远不要返回指向局部变量的指针,因为它会消失.
tho*_*ter 20
我发现答案不尽如人意,所以我会加两分钱.
我们来分析下列情况:
int& getInt()
{
int x = 4;
return x;
}
Run Code Online (Sandbox Code Playgroud)
这显然是错误的
int& x = getInt(); // will refer to garbage
Run Code Online (Sandbox Code Playgroud)
int& getInt()
{
static int x = 4;
return x;
}
Run Code Online (Sandbox Code Playgroud)
这是对的,因为静态变量在程序的整个生命周期中都是存在的.
int& x = getInt(); // valid reference, x = 4
Run Code Online (Sandbox Code Playgroud)
这在实现Singleton模式时也很常见
Class Singleton
{
public:
static Singleton& instance()
{
static Singleton instance;
return instance;
};
void printHello()
{
printf("Hello");
};
}
Run Code Online (Sandbox Code Playgroud)
用法:
Singleton& my_sing = Singleton::instance(); // Valid Singleton instance
my_sing.printHello(); // "Hello"
Run Code Online (Sandbox Code Playgroud)
例如,标准库容器严重依赖于返回引用的运算符的使用
T & operator*();
Run Code Online (Sandbox Code Playgroud)
可以在下面使用
std::vector<int> x = {1, 2, 3}; // create vector with 3 elements
std::vector<int>::iterator iter = x.begin(); // iterator points to first element (1)
*iter = 2; // modify first element, x = {2, 2, 3} now
Run Code Online (Sandbox Code Playgroud)
有时可以使用&可以快速访问内部数据
Class Container
{
private:
std::vector<int> m_data;
public:
std::vector<int>& data()
{
return m_data;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
Container cont;
cont.data().push_back(1); // appends element to std::vector<int>
cont.data()[0] // 1
Run Code Online (Sandbox Code Playgroud)
但是,这可能导致诸如此类的陷阱:
Container* cont = new Container;
std::vector<int>& cont_data = cont->data();
cont_data.push_back(1);
delete cont; // This is bad, because we still have a dangling reference to its internal data!
cont_data[0]; // dangling reference!
Run Code Online (Sandbox Code Playgroud)
Meh*_*ari 14
这不是邪恶的.像C++中的许多东西一样,如果正确使用它会很好,但是在使用它时你应该注意许多陷阱(比如返回对局部变量的引用).
用它可以实现好东西(比如map [name] ="hello world")
Joh*_*ing 10
"返回引用是邪恶的,因为,根据我的理解,它更容易错过删除它"
不对.返回引用并不意味着所有权语义.也就是说,仅仅因为你这样做:
Value& v = thing->getTheValue();
Run Code Online (Sandbox Code Playgroud)
......并不意味着你现在拥有v所指的记忆;
但是,这是一个可怕的代码:
int& getTheValue()
{
return *new int;
}
Run Code Online (Sandbox Code Playgroud)
如果你正在做这样的事情,因为"你不需要在该实例上使用指针",那么:1)如果需要引用,只需取消引用指针,2)你最终需要指针,因为你必须匹配一个带删除的new,你需要一个指向调用delete的指针.
小智 7
有两种情况:
const引用 - 很好的想法,有时候,特别是对于重型对象或代理类,编译器优化
非常规引用 - 有时会破坏封装
两者都有相同的问题 - 可能潜在地指向被破坏的对象......
我建议在需要返回引用/指针的许多情况下使用智能指针.
另请注意以下事项:
有一个正式的规则 - C++标准(如果你感兴趣,请参见第13.3.3.1.4节)声明临时只能绑定到const引用 - 如果你尝试使用非const引用,编译器必须将其标记为一个错误.