【问题标题】:Access to the template class constructor's parameter from the destructor, is it possible?从析构函数访问模板类构造函数的参数,可以吗?
【发布时间】:2018-12-08 14:54:30
【问题描述】:

我想看看如何从析构函数中访问构造函数的参数。在这个例子中,我想从构造函数中修改参数并在析构函数中恢复它。

template<typename T>
class sorted_array_view {
public:    
    sorted_array_view(T* givenArray,size_t size) {
         for( int idx = 0; idx < size; ++idx){
            data.push_back(givenArray[idx]);
            originaldata.push_back(givenArray[idx]);
         }
         std::sort(data.begin(), data.end());
         for(int idx =0; idx<size; ++idx){
            givenArray[idx] = data.at(idx);
         }
    }

    ~sorted_array_view(){
         for(int idx =0; idx<size; ++idx){
            givenArray[idx] = originaldata.at(idx);
         }
    }

private:
    std::vector<T> data;
    std::vector<T> originaldata;
};

但我在析构函数中收到错误'givenArray' was not declared in this scope。如何访问givenArray

【问题讨论】:

  • 可以在类中存储构造函数的参数
  • @Tyker 作为参考?
  • 什么是givenArray,为什么不是std::vector
  • @KorteAlma - 没有什么可以阻止引用成为类的成员,由构造函数初始化并由析构函数访问。当析构函数使用它时,由类的用户确保被引用的对象仍然存在(使用悬空引用(也就是对不再存在的对象的引用给出未定义的行为))。

标签: c++ oop templates constructor destructor


【解决方案1】:

只需将givenArray 设为该类的数据成员即可。

然后析构函数(和任何其他成员函数)将可以访问它。


PS:将析构函数中的size 更改为originaldata.size(),如果它们的值相同(这似乎是您的代码的情况)。否则,您也需要size 成为数据成员。

【讨论】:

  • 原始数据向量已经保存了大小,只需将size更改为originaldata.size()即可。
  • 谢谢@MaLarsson,很好的观察,但前提是originaldata 不会改变,我应该提一下。
【解决方案2】:

一般来说,在一个类中,如果你想从另一个成员函数中访问一个成员函数的参数,你需要将该参数存储在类中。

总的来说,简化你的代码,它给出了:

template<typename T>
struct sorted_array_view
{    
    sorted_array_view(T* array, std::size_t size)
        : original_content{array, array+size}, original_container{array}
    {
        std::sort(array, array+size);
    }

    ~sorted_array_view()
    {
        std::copy(begin(original_content), end(original_content), original_container);
    }

private:
    std::vector<T> original_content;
    T*             original_container;
};

完整演示:http://coliru.stacked-crooked.com/a/2958a997404bfaf9

【讨论】:

  • 啊,你也打我了,我太完整了;)
【解决方案3】:

使用更多的 STL,你的代码甚至可以变成

#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
class sorted_array_view {
public:
    sorted_array_view(T* const givenArray, size_t size)
        : data(givenArray, givenArray + size)
        , originaldata(givenArray, givenArray + size)
        , givenArray(givenArray)
    {
        std::sort(data.begin(), data.end());
        std::copy(std::cbegin(data), std::cend(data), givenArray);
    }

    ~sorted_array_view() {
        std::copy(std::cbegin(originaldata), std::cend(originaldata), givenArray);
    }

private:
    std::vector<T> data;
    std::vector<T> const originaldata;
    T* const givenArray;
};

#include <array>
#include <iostream>
int main()
{
    std::array<int, 5> givenArray = { 4, 3, 5, 1, 2 };

    {
        sorted_array_view<int> sortTemp(&givenArray[0], givenArray.size());

        for (const auto& el : givenArray) std::cout << el << " "; std::cout << "\n";
    }
    for (const auto& el : givenArray) std::cout << el << " "; std::cout << "\n";
}

输出:

1 2 3 4 5 
4 3 5 1 2 

live example

但是在你的构造函数/析构函数中做太多是很危险的。 你不能从析构函数中抛出异常。 编辑:见 Peter 的评论。

【讨论】:

  • 异常可以从析构函数中抛出。然而,在实践中它很少是一个好主意,因为它严重限制了对象的效用,例如不能在标准容器中轻松存储/使用,如果在堆栈展开期间调用析构函数,则会调用 std::terminate(),因为抛出了另一个异常等。
猜你喜欢
  • 2018-05-18
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 2018-06-23
  • 2011-02-11
  • 2011-02-21
  • 2014-05-22
  • 2016-01-02
相关资源
最近更新 更多