C++-如果我`return a*=b;`会发生什么
C++ - What happens if I `return a*= b;`?
所以。。我正在写一些代码,想知道复合运算符的原型(例如operator*=
或operator/=
)。当我查找它时,我意识到他们应该返回参考资料。(或者至少我的消息来源是这样的:R& operator +=(K& a, S b);
。)嗯。。然后我意识到我代码中的一行可能比看起来更危险:
// I have a really fancy Vector class I've been making. :P
template<typename T, int N>
inline Vector<T, N> operator*(const Vector<T, N>& vec, T scale) {
Vector<T, N> ret = vec;
return ret *= scale;
}
所以。。我想知道这是否无害。。。或者将导致对局部变量的引用泄漏,并导致各种未定义的行为和一般的破坏。(我倾向于浩劫,因此,重写如下。:P)
// I have a really fancy Vector class I've been making. :P
template<typename T, int N>
inline Vector<T, N> operator*(const Vector<T, N>& vec, T scale) {
Vector<T, N> ret = vec;
ret *= scale;
return ret;
}
所以。。是的。。一般的C++"如果?"问题。很高兴能确定。(我也懒得做一个测试用例,看看我的程序是否停止并起火。:P)
编辑:修复上述代码后。。我意识到把上述复合运算符也放在这里可能会有所帮助P
template<typename T, int N>
inline Vector<T, N>& operator*=(Vector<T, N>& vec, T scale) {
for (int i = 0; i < N; i++) {
vec[i] *= scale;
}
return vec;
}
所以。。经过代码更正(并仔细检查)后,我想知道使用第一个变体是否仍然会导致悬空引用(因为operator*=
的返回类型是引用)。
按照惯例,像*=
这样的复合赋值运算符应该返回对它们修改的对象的引用,因为没有理由进行不必要的复制。也就是说,即使在修改后的示例中,您也会得到一个"悬空"引用,因为您仍在返回对局部变量的引用,该变量在函数返回后将被销毁。您应该按值而不是按引用返回。
template <typename T, int N>
Vector<T, N> operator*(Vector<T, N> const& vec, T scale) {
Vector<T, N> ret = vec;
return ret *= scale;
}
还要注意,如果按值传递vec
,则可以去掉ret
。如果CCD_ 8可以被更有效地移动而不是被复制,则这可以允许更有效的客户端代码。
template <typename T, int N>
Vector<T, N> operator*(Vector<T, N> vec, T scale) {
return vec *= scale;
}
(虽然@JosephThomson下面的答案"回答"了这个问题,但它并没有像我认为的那样简单,所以我在这里提供答案。)
template<typename T, int N>
inline Vector<T, N> operator*(const Vector<T, N>& vec, T scale) {
Vector<T, N> ret = vec;
return ret *= scale;
}
上述中的return ret *= scale;
不会导致悬空参考错误。原因是返回类型是Vector<T, N>
,并且是而不是引用类型。因此,即使operator*=
被定义为返回引用类型,当operator*
返回时也会产生一个副本(有效地剥离引用)。
您有两个选择:
如果您在类中定义运算符,它将使用一个参数,然后修改类数据并返回*this而不返回局部变量:
R& K::operator *=(S b);
如果你在类外定义运算符,它需要两个参数,你修改该参数并返回该参数,而不返回局部变量:
R& operator *=(K& a, S b);
发件人http://en.cppreference.com/w/cpp/language/operators在规范实现下,他们有这样的例子:
class X
{
public:
X& operator+=(const X& rhs) // compound assignment (does not need to be a member,
{ // but often is, to modify the private members)
/* addition of rhs to *this takes place here */
return *this; // return the result by reference
}
// friends defined inside class body are inline and are hidden from non-ADL lookup
friend X operator+(X lhs, // passing lhs by value helps optimize chained a+b+c
const X& rhs) // otherwise, both parameters may be const references
{
lhs += rhs; // reuse compound assignment
return lhs; // return the result by value (uses move constructor)
}
};
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- C++如果必须在编译时确定大小,std::array 有什么意义?
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 如果我在 const 函数上使用指针,我可以返回什么?
- 基本的 c++ 问题:如果我在函数中创建某些内容并返回它会发生什么?
- 如果我在字符数组上使用 close() 会发生什么?
- 如果在双引号末尾传递逗号(,),"cout"的行为是什么?
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- 如果我向一个12字节的缓冲区写入的字节数少于12,会发生什么情况
- 如果与memory_order_acquire一起存储会发生什么
- 如果我们不从 std::qsort 返回 0 会发生什么?
- 如果我在 c++ 中以 new 的放置形式使用没有足够的内存,会发生什么情况?
- 如果在 C++ 构造函数中以错误的顺序初始化对象数据,会发生什么类型的错误
- 如果我使用同一个密钥推送用户数据两次,会发生什么
- 这个问题叫什么?如果通过基类型传递结构,则后代类型中的字段在方法中不可用
- {1, 2} 是值吗?如果是,它的类型是什么?如果不是,为什么可以将其分配给初始值设定项列表
- 什么'如果pthread_cond_wait自己这样做,那么锁定和解锁互斥锁的意义就在于什么
- 这个宏语句是合法的C++还是其他什么?如果它是合法的,它是如何运作的