Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何解决悬空常量ref_C++ - Fatal编程技术网

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