C++ 如何解决悬空常量ref
下面是简短的节目C++ 如何解决悬空常量ref,c++,C++,下面是简短的节目 #include <vector> #include <iostream> std::vector<int> someNums() { return {3, 5, 7, 11}; } class Woop { public: Woop(const std::vector<int>& nums) : numbers(nums) {} void report() { for
#include <vector>
#include <iostream>
std::vector<int> someNums()
{
return {3, 5, 7, 11};
}
class Woop
{
public:
Woop(const std::vector<int>& nums) : numbers(nums) {}
void report()
{
for (int i : numbers)
std::cout << i << ' ';
std::cout << '\n';
}
private:
const std::vector<int>& numbers;
};
int main()
{
Woop woop(someNums());
woop.report();
}
#包括
#包括
std::vector someNums()
{
返回{3,5,7,11};
}
类低音
{
公众:
Woop(const std::vector&nums):数字(nums){}
作废报告()
{
用于(int i:数字)
std::cout为了防止这种特殊情况,您可以选择使用指针(因为Weep(&std::vector{1,2,3})
是不允许的),或者使用非常量引用,这也会导致临时错误
Woop(const std::vector<int> *nums);
Woop(std::vector<int> *nums);
Woop(std::vector<int>& nums);
或者,如果所有权是共享的,您可以对所有内容使用shared\u ptr
,它将与最终引用一起删除,但如果使用过度,这可能会使跟踪对象生命周期变得非常混乱。我同意其他答案和注释,如果您确实需要将引用存储到如果你这样做,你可能需要一个指向常量向量的非常量指针(即std::vector const*numbers
)
然而,如果是这样的话,我发现目前发布的其他答案与问题无关。它们都向您展示了如何使Woop
拥有这些值
如果可以确保传入的向量比Woop
实例的寿命长,则可以显式禁用从右值构造Woop
。这可以使用以下C++11语法实现:
Woop (std::vector<int> const &&) = delete;
Woop(std::vector const&&)=删除;
现在,您的示例代码将不再编译。具有的编译器将给出类似于以下内容的错误:
prog.cc: In function 'int main()':
prog.cc:29:25: error: use of deleted function 'Woop::Woop(const std::vector<int>&&)'
29 | Woop woop(someNums());
| ^
prog.cc:15:5: note: declared here
15 | Woop(std::vector<int> const &&) = delete;
| ^~~~
prog.cc:在函数“int main()”中:
程序cc:29:25:错误:使用删除的函数“Woop::Woop(const std::vector&)”
29 |呜呜(someNums());
| ^
进度cc:15:5:注:此处声明
15|Woop(std::vector const&&)=删除;
| ^~~~
注意:您可能需要一个显式构造函数,请参见,例如…使类不易受攻击的一种方法是添加一个带右引用的已删除构造函数。这将阻止类实例绑定到临时对象
Woop(std::vector<int>&& nums) =delete;
Woop(std::vector&&nums)=删除;
此已删除的构造函数实际上会使O/p代码无法编译,这可能是您正在寻找的行为?在某些方法返回后保留引用的情况下,最好使用
std::reference\u wrapper
而不是普通引用:
#include <functional>
class Woop
{
public:
using NumsRef = ::std::reference_wrapper<const std::vector<int>>;
Woop(NumsRef nums) : numbers_ref{nums} {}
void report()
{
for (int i : numbers_ref.get())
std::cout << i << ' ';
std::cout << '\n';
}
private:
NumsRef numbers_ref;
};
如果您想要拥有一个包含
const
容器的对象,可以使用template programming
和arrays
。由于constepr
构造函数和constepr arrays
可以实现const正确性
和编译时执行
以下是一篇可能很有趣的帖子:
这是棘手的。我可以告诉你,在我做一个成员变量const引用之前,我会三思而后行。如果有疑问,我会考虑用某种方法来模拟这个数据。(对于独占所有权,或者
std::unique_ptr
,或者std::shared_ptr
或者共享所有权,或者std::weak_ptr
至少可以识别丢失的数据)C++中,你不为你不需要的东西付费。程序员需要注意,引用对象的生命周期不会在引用仍然在使用/存在的时候结束。同样的事情,原始指针,有智能指针给你带来你所要求的特性:引用成员总是一个错误:虽然编译器没有发出警告,但Valgrind和-fsanize=address
可以捕获此错误。我认为没有任何最佳做法可以避免此错误而不牺牲性能。另请参见:将数字作为std::array
这保证可以复制,即使移动是ava我可以。除此之外,wooping1
和wooping2
不是同一种类型,这不太理想。@SP2非常感谢您的反馈,我必须在这两点上同意您的意见。user7860670提供了一个更好的解决方案:)我似乎偷了您的答案。抱歉!
#include <functional>
class Woop
{
public:
using NumsRef = ::std::reference_wrapper<const std::vector<int>>;
Woop(NumsRef nums) : numbers_ref{nums} {}
void report()
{
for (int i : numbers_ref.get())
std::cout << i << ' ';
std::cout << '\n';
}
private:
NumsRef numbers_ref;
};
Woop woop{someNums()}; // error
woop.report();
auto nums{someNums()};
Woop woop{nums}; // ok
woop.report();
auto nums{someNums()};
Woop woop{::std::ref(nums)}; // even better because explicit
woop.report();
#include <array>
#include <iostream>
#include <vector>
std::array<int,4> someNums()
{
return {3, 5, 7, 11};
}
template<typename U, std::size_t size>
class Woop
{
public:
template<typename ...T>
constexpr Woop(T&&... nums) : numbers{nums...} {};
template<typename T, std::size_t arr_size>
constexpr Woop(std::array<T, arr_size>&& arr_nums) : numbers(arr_nums) {};
void report()
const {
for (auto&& i : numbers)
std::cout << i << ' ';
std::cout << '\n';
}
private:
const std::array<U, size> numbers;
//constexpr vector with C++20
};
int main()
{
Woop<int, 4> wooping1(someNums());
Woop<int, 7> wooping2{1, 2, 3, 5, 12 ,3 ,51};
wooping1.report();
wooping2.report();
return 0;
}
3 5 7 11
1 2 3 5 12 3 51