当前位置: 首页 > 知识库问答 >
问题:

C:如何创建一个临时对象,包含指针常量或非常量,具体取决于上下文?

姬魁
2023-03-14

我想在向量中保存一些结构Data。这些结构通过索引(而不是指针)引用其他结构,以节省内存并使序列化更容易。为了遵循这些索引,我创建了一个类DataView,它为它提供了一个舒适的界面。它看起来像这样:

#include <iostream>
#include <vector>

struct Data
{
    int id_next;
    int id_prev;
    int value;
};

class Foo;

class DataView
{
    Foo * foo;
    int index;
public:
    DataView( Foo * foo_, int index_ )
        : foo( foo_ ), index( index_ )
    {
    }
    DataView next() const;
    DataView prev() const;
    int value() const;
    int & value();
    int id() const
    {
        return index;
    }
};

class Foo
{
    std::vector<Data> data;
public:
    friend class DataView;

    DataView dataview( int index )
    {
        return DataView( this, index );
    }

    Foo()
    {
        data.resize( 5 );
        for ( int i = 0; i < (int)data.size(); i++ )
        {
            data[i].id_next = (i + 1) % data.size();
            data[i].id_prev = (i + 4) % data.size();
            data[i].value = i * i;
        }
    }

    void write_cycle( int start_index ) // const
    {
        DataView seek = dataview( start_index );
        do
        {
            std::cout << "index " << seek.id() << " value " << seek.value() << std::endl;
            seek = seek.next();
        } while ( seek.id() != start_index );
    }
};

DataView DataView::next() const
{
    return DataView( foo, foo->data[index].id_next );
}
DataView DataView::prev() const
{
    return DataView( foo, foo->data[index].id_prev );
}
int DataView::value() const
{
    return foo->data[index].value;
}
int & DataView::value()
{
    return foo->data[index].value;
}

int main()
{
    Foo foo;
    foo.write_cycle( 3 );
    foo.dataview( 2 ).value() = 11;
    foo.write_cycle( 3 );
    return 0;
}

如果必须区分dataview方法的常量和非常量变体,就会出现问题。事实上,write\u cycle应该是const,因为它不会改变任何东西。然而,如果取消注释const限定符,则会出现编译器错误。

错误:将“const Foo”传递为“this”参数会丢弃限定符[-fpermissive]

如何编写包含常量或非常量指针的数据视图,这取决于它的构造函数是用常量还是非常量指针调用的?

共有3个答案

徐丰茂
2023-03-14

用户添加Sahu关于在数据视图中将Foo保留为const的回答,因为它将作为只读类,不应修改Foo;您可以将此函数添加到Foo的类中以更新其值:

void Foo::updateValue( int index, const int& value ) {
    if ( index < 0 || index >= data.size() ) {
        return;
    }

    data[index].value = value;
}

然后在主管道内。cpp文件如下所示:

Foo foo;
std::cout << "writing cycle of 3" << std::endl;
foo.write_cycle( 3 );
std::cout << "updating index 2 with value of 11" << std::endl;
foo.updateValue( 2, 11 );
std::cout << "writing cycle of 3" << std::endl;
foo.write_cycle( 3 );
慕晨
2023-03-14

如果一个方法是const,那么它所做的或提供的任何操作都不允许更改实例。这包括该方法调用的任何函数或其他方法,以及对该方法返回的任何成员的引用必须是const,以便将来不能使用它们修改对象。

因此,如果写入周期是常量,那么数据视图必须是常量,并且数据视图必须有一个接受常量的构造函数。这意味着要接受常量foo的赋值,foo也必须是常量。如果DataView的客户端希望操作存储的Foo,这可能会出现问题。

最终结果是,如果没有大量的额外工作,write\u cycle不可能是常量。

魏楷
2023-03-14

你说:

这些结构通过索引(而不是指针)引用其他结构,以节省内存并简化序列化。为了遵循这些索引,我创建了一个类DataView,它为它提供了一个舒适的界面。

这向我表明,您不需要支持:

foo.dataview( 2 ).value() = 11;

使用数据视图仅读取数据。如果您同意这一点,您可以更改数据视图来存储一个Foo const*。然后,您可以去掉非const版本的DataView::value()。

class DataView
{
    Foo const* foo;
    int index;
public:
    DataView( Foo const* foo_, int index_ )
        : foo( foo_ ), index( index_ )
    {
    }
    DataView next() const;
    DataView prev() const;
    int value() const;

    // Don't need this.
    // int & value();

    int id() const
    {
        return index;
    }
};
 类似资料:
  • 本文向大家介绍详解C语言中的常量指针和指针常量,包括了详解C语言中的常量指针和指针常量的使用技巧和注意事项,需要的朋友参考一下 概述 对于新手来说,指针在c语言里总是一个非常难以理解的概念。在这篇文章中,我们将解释常量指针,指针常量,const pointer to const(ps:楼主以为这可以翻译成指向常量的常量指针)的区别 常量指针 让我们先来理解什么是常量指针。常量指针是指指针指向的地址

  • 本文向大家介绍C++常量详解一(常量指针与常量引用的初始化),包括了C++常量详解一(常量指针与常量引用的初始化)的使用技巧和注意事项,需要的朋友参考一下 1、常量 1.1、常量的初始化: const对象一旦创建后其值就不能再改变,所以const对象必须初始化。这里我们要注意一点,像const int *p和const int &r都并不是const对象。因为const int *p只是表示不能通

  • 此代码未编译,因为被视为

  • 我创建了2个函数,读取和写入一个路径,声明为: 我创建了一个额外的函数,它将使用路径调用上述函数之一 但是,当作为回调传递给时,编译器会发出以下警告 将“int(const char*,const void,int)”传递给类型为“int()(const char*,void*,int)”的参数的指针类型不兼容 将接受常量指针的函数转换为接受非常量指针的函数会是未定义的行为吗? 我注意到有一个几乎

  • 我们看到在GCC 11.3和Visual Studio 2022中成功编译的C代码在GCC 12.1中存在问题。该代码位于编译器资源管理器:https://godbolt.org/z/6PYEcsd1h(感谢@NathanPierson对其进行了一些简化。) 基本上,模板类决定尝试在const函数中调用非const基类函数,即使const重载可用。这似乎是某种编译器错误,但可能是一些奇怪的新C规则

  • 本文向大家介绍如何判断一个常量是废弃常量 ?相关面试题,主要包含被问及如何判断一个常量是废弃常量 ?时的应答技巧和注意事项,需要的朋友参考一下 运行时常量池主要回收的是废弃的常量。那么,我们如何判断一个常量是废弃常量呢? 假如在常量池中存在字符串 "abc",如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 "abc" 就是废弃常量,如果这时发生内存回收的话而且有必要的话,"a