C++11:防止对象被分配给引用
有没有办法创建一个类型 A
这样:
给定:
A f(...);
然后:
两者 auto&& a = f(...);
和 const auto& a = f(...);
给出编译错误?
原因是在这种情况下, A
是一个表达式模板,其中包含对临时变量的引用(作为 f
的参数提供),所以我不希望该对象的生命周期超出了当前表达式。
请注意,我可以通过将 A
的复制构造函数设置为私有并将 f(.. .)
A 的朋友(如果需要)。
代码示例 (ideone 链接):
#include <iostream>
#include <array>
template <class T, std::size_t N>
class AddMathVectors;
template <class T, std::size_t N>
class MathVector
{
public:
MathVector() {}
MathVector(const MathVector& x)
{
std::cout << "Copying" << std::endl;
for (std::size_t i = 0; i != N; ++i)
{
data[i] = x.data[i];
}
}
T& operator[](std::size_t i) { return data[i]; }
const T& operator[](std::size_t i) const { return data[i]; }
private:
std::array<T, N> data;
};
template <class T, std::size_t N>
class AddMathVectors
{
public:
AddMathVectors(const MathVector<T,N>& v1, const MathVector<T,N>& v2) : v1(v1), v2(v2) {}
operator MathVector<T,N>()
{
MathVector<T, N> result;
for (std::size_t i = 0; i != N; ++i)
{
result[i] = v1[i];
result[i] += v2[i];
}
return result;
}
private:
const MathVector<T,N>& v1;
const MathVector<T,N>& v2;
};
template <class T, std::size_t N>
AddMathVectors<T,N> operator+(const MathVector<T,N>& v1, const MathVector<T,N>& v2)
{
return AddMathVectors<T,N>(v1, v2);
}
template <class T, std::size_t N>
MathVector<T, N> ints()
{
MathVector<T, N> result;
for (std::size_t i = 0; i != N; ++i)
{
result[i] = i;
}
return result;
}
template <class T, std::size_t N>
MathVector<T, N> squares()
{
MathVector<T, N> result;
for (std::size_t i = 0; i != N; ++i)
{
result[i] = i * i;
}
return result;
}
int main()
{
// OK, notice no copies also!
MathVector<int, 100> x1 = ints<int, 100>() + squares<int, 100>();
// Should be invalid, ref to temp in returned object
auto&& x2 = ints<int, 100>() + squares<int, 100>();
}
Is there any way to create a type A
such that:
Given:
A f(...);
Then:
Both auto&& a = f(...);
and const auto& a = f(...);
give a compile errors?
The reason for this is that in this case, A
is an expression template which contains references to temporaries (that are provided as arguments to f
), so I don't want the lifetime of this object extended beyond the current expression.
Note I can prevent auto a = f(...);
from being an issue just by making A
s copy constructor private, and making f(...)
a friend of A if required.
Example of code (ideone link):
#include <iostream>
#include <array>
template <class T, std::size_t N>
class AddMathVectors;
template <class T, std::size_t N>
class MathVector
{
public:
MathVector() {}
MathVector(const MathVector& x)
{
std::cout << "Copying" << std::endl;
for (std::size_t i = 0; i != N; ++i)
{
data[i] = x.data[i];
}
}
T& operator[](std::size_t i) { return data[i]; }
const T& operator[](std::size_t i) const { return data[i]; }
private:
std::array<T, N> data;
};
template <class T, std::size_t N>
class AddMathVectors
{
public:
AddMathVectors(const MathVector<T,N>& v1, const MathVector<T,N>& v2) : v1(v1), v2(v2) {}
operator MathVector<T,N>()
{
MathVector<T, N> result;
for (std::size_t i = 0; i != N; ++i)
{
result[i] = v1[i];
result[i] += v2[i];
}
return result;
}
private:
const MathVector<T,N>& v1;
const MathVector<T,N>& v2;
};
template <class T, std::size_t N>
AddMathVectors<T,N> operator+(const MathVector<T,N>& v1, const MathVector<T,N>& v2)
{
return AddMathVectors<T,N>(v1, v2);
}
template <class T, std::size_t N>
MathVector<T, N> ints()
{
MathVector<T, N> result;
for (std::size_t i = 0; i != N; ++i)
{
result[i] = i;
}
return result;
}
template <class T, std::size_t N>
MathVector<T, N> squares()
{
MathVector<T, N> result;
for (std::size_t i = 0; i != N; ++i)
{
result[i] = i * i;
}
return result;
}
int main()
{
// OK, notice no copies also!
MathVector<int, 100> x1 = ints<int, 100>() + squares<int, 100>();
// Should be invalid, ref to temp in returned object
auto&& x2 = ints<int, 100>() + squares<int, 100>();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
给定任何临时对象,在 C++ 中通过将其绑定到 const& 或
&&
变量来延长该临时对象的生命周期始终是合法的。最终,如果您正在处理惰性求值等问题,则必须要求用户不要使用const auto &
或auto &&
。 C++11 中没有任何内容可以让您强行阻止用户这样做。Given any temporary object, it is always legal in C++ to extend the lifetime of that temporary by binding it to a
const&
or&&
variable. Ultimately, if you're dealing with lazy evaluation and the like, you have to ask the user not to useconst auto &
orauto &&
. There's nothing in C++11 that allows you to forcibly prevent the user from doing so.