Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.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
如何避免将句柄返回到对象内部-第28项有效C++; 有效C++的第28项说明避免返回“句柄”到对象内部结构< /代码>。演示如何通过考虑封装来设计代码,从而避免意外地暴露类的内部_C++_Effective C++_Dangling Pointer - Fatal编程技术网

如何避免将句柄返回到对象内部-第28项有效C++; 有效C++的第28项说明避免返回“句柄”到对象内部结构< /代码>。演示如何通过考虑封装来设计代码,从而避免意外地暴露类的内部

如何避免将句柄返回到对象内部-第28项有效C++; 有效C++的第28项说明避免返回“句柄”到对象内部结构< /代码>。演示如何通过考虑封装来设计代码,从而避免意外地暴露类的内部,c++,effective-c++,dangling-pointer,C++,Effective C++,Dangling Pointer,我的示例涉及一个数据数组,由于内存是一个问题,我希望避免使用std::vector(以及Boost库) 使用数组这是我的代码的一个非常简化的版本: class Foo { public: Foo(int size) : data_(new int[size]) { // Populate with data just for the example for(int i = 0; i < size; i++) { data_[i

我的示例涉及一个数据数组,由于内存是一个问题,我希望避免使用
std::vector
(以及Boost库)

使用数组这是我的代码的一个非常简化的版本:

class Foo {
public:
    Foo(int size) : data_(new int[size]) {
        // Populate with data just for the example
        for(int i = 0; i < size; i++) {
            data_[i] = i;
        }
    }

    // I know that this isn't good practice
    int* const get_data() const {
        return data_;
    }

    ~Foo() {
        delete[] data_;
    }

private:
    int* data_;
};

int main(void) {
    Foo* foo = new Foo(10);
    int* const data = foo->get_data();
    delete foo;
    // data now dangles which is bad!
    return 0;
}
class-Foo{
公众:
Foo(整数大小):数据(新整数[大小]){
//仅为示例填充数据
对于(int i=0;iget_data();
删除foo;
//数据现在悬空,这是坏的!
返回0;
}

我理解将
const
get_data()
一起使用并不能保证安全。如果我使用的是向量,我可以像上面的示例问题那样复制它,但由于我想避免这种情况,我想知道如何最好地设计我的类以避免这种潜在的危险情况?

在您的情况下,一种方法是使用智能指针。我更喜欢。以下是如何修改类以避免出现问题:

class Foo {
public:
    Foo(int size) : data_(new int[size]) {
        // Populate with data just for the example
        for(int i = 0; i < size; i++) {
            data_[i] = i;
        }
    }

    // I know that this isn't good practice
    std::shared_ptr<int> const get_data() const {
        return data_;
    }

    ~Foo() {
        //delete[] data_;
    }

private:
    std::shared_ptr<int> data_;
};

int main(void) {
    Foo* foo = new Foo(10);
    std::shared_ptr<int> data = foo->get_data();
    delete foo;
    // data still good )) // --now dangles which is bad!--
    return 0;
}
class-Foo{
公众:
Foo(整数大小):数据(新整数[大小]){
//仅为示例填充数据
对于(int i=0;iget_data();
删除foo;
//数据仍然是好的)]/--现在是坏的--
返回0;
}

在您的情况下,一种方法是使用智能指针。我更喜欢。以下是如何修改类以避免出现问题:

class Foo {
public:
    Foo(int size) : data_(new int[size]) {
        // Populate with data just for the example
        for(int i = 0; i < size; i++) {
            data_[i] = i;
        }
    }

    // I know that this isn't good practice
    std::shared_ptr<int> const get_data() const {
        return data_;
    }

    ~Foo() {
        //delete[] data_;
    }

private:
    std::shared_ptr<int> data_;
};

int main(void) {
    Foo* foo = new Foo(10);
    std::shared_ptr<int> data = foo->get_data();
    delete foo;
    // data still good )) // --now dangles which is bad!--
    return 0;
}
class-Foo{
公众:
Foo(整数大小):数据(新整数[大小]){
//仅为示例填充数据
对于(int i=0;iget_data();
删除foo;
//数据仍然是好的)]/--现在是坏的--
返回0;
}

编程和软件设计是一个不断的“选择”。如果您确实负担不起使用
std::vector
,并且需要使用类向客户机代码公开数据,那么就这样吧。记录为什么会这样,并确保随着时间的推移对其进行审查——可能是当您的新型号硬件具有8MB的RAM而不是2MB时,将能够使用额外的4字节,而
矢量
将接管您的普通指针

或编写访问器函数:

int& Foo::operator[](int pos)
{
   // Add checks here to ensure `pos` is in range?
   return data[pos]; 
}

现在您根本不必返回指针

编程和软件设计是一种不断的“选择”。如果您确实负担不起使用
std::vector
,并且需要使用类向客户机代码公开数据,那么就这样吧。记录为什么会这样,并确保随着时间的推移对其进行审查——可能是当您的新型号硬件具有8MB的RAM而不是2MB时,将能够使用额外的4字节,而
矢量
将接管您的普通指针

或编写访问器函数:

int& Foo::operator[](int pos)
{
   // Add checks here to ensure `pos` is in range?
   return data[pos]; 
}

现在您根本不必返回指针

如果您确实希望避免使用std::vector,可以实现类似于某些winapi函数所使用的方法

size_t get_data(int* data_ptr, size_t& buffer_size)
{
if(buffer_size < sizeof (data_)
{
buffer_size = sizeof(data);
return 0;
}
//You could you memcpy for ints here
        for(int i = 0; i < size; i++) {
            data_ptr[i] = i;
        }
return sizof(data_);
}
size\u t获取数据(int*data\u ptr、size\u t和buffer\u size)
{
如果(缓冲区大小
因此,要求调用方提供内存来存储数据,并关心该内存的分配。
通过它,std::vector应该可以在安全性大大降低的情况下重新发明。
另外,在开始更广泛地使用类时,您应该检查以避免出现问题。

如果您确实希望避免使用std::vector,您可以实现类似于某些winapi函数所使用的方法

size_t get_data(int* data_ptr, size_t& buffer_size)
{
if(buffer_size < sizeof (data_)
{
buffer_size = sizeof(data);
return 0;
}
//You could you memcpy for ints here
        for(int i = 0; i < size; i++) {
            data_ptr[i] = i;
        }
return sizof(data_);
}
size\u t获取数据(int*data\u ptr、size\u t和buffer\u size)
{
如果(缓冲区大小
因此,要求调用方提供内存来存储数据,并关心该内存的分配。
通过它,std::vector应该可以在安全性大大降低的情况下重新发明。
此外,当您开始更广泛地使用类时,您应该检查以避免出现问题。

在许多情况下,返回指针是完全可以接受的,即使数组实际上包含在
std::vector
中;例如,使用外部API和复制数据时不受欢迎

我不认为有什么危险,因为你不是在为猴子编程。这个类的用户应该知道。但我添加了查询数据大小的函数。这是为了安全

extern "C"{
void foobar( const int *data, unsigned int size );
}
class Foo {
public:
    Foo(unsigned int size) : size_(size), data_(new int[size]) {
        // Populate with data just for the example
        for(unsigned int i = 0; i < size; i++) {
            data_[i] = i;
        }
    }

    unsigned int get_size() const{return size_;}
    int* const get_data() const {
        return data_;
    }

    ~Foo() {
        delete[] data_;
    }

private:
    int* data_;
    unsigned int size_;
};

int main(void) {
    Foo* foo = new Foo(10);
    int* const data = foo->get_data();
    foobar( data, foo->get_size() );
    delete foo;
    return 0;
}
extern“C”{
void foobar(常量整型*数据,无符号整型大小);
}
福班{
公众:
Foo(无符号整数大小):大小(大小),数据(新整数[大小]){
//仅为示例填充数据
对于