Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.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++ C++;:有没有一种有效的方法在语法上使用指针之类的索引?_C++_Pointers - Fatal编程技术网

C++ C++;:有没有一种有效的方法在语法上使用指针之类的索引?

C++ C++;:有没有一种有效的方法在语法上使用指针之类的索引?,c++,pointers,C++,Pointers,这是我的旅程,我试图为一个我怀疑经常出现的问题获得一些零开销语法便利。我对C++很陌生,所以我希望有人能给我一个更好的解决方案。给出的所有代码都应该在C++11下编译和运行。还要注意的是,尽管我的解决方案涉及到使用指针的语法,但我对“与使用指针一样简单”很满意 我有一些代码使用对象网络,对象之间有指针,如下所示。(为了简单起见,我这里的示例只是一个链表,但实际结构更为复杂-a。) #包括 结构节点{ int-val; 节点*下一步; }; int main() { Node*a=新节点(); N

这是我的旅程,我试图为一个我怀疑经常出现的问题获得一些零开销语法便利。我对C++很陌生,所以我希望有人能给我一个更好的解决方案。给出的所有代码都应该在C++11下编译和运行。还要注意的是,尽管我的解决方案涉及到使用指针的语法,但我对“与使用指针一样简单”很满意

我有一些代码使用对象网络,对象之间有指针,如下所示。(为了简单起见,我这里的示例只是一个链表,但实际结构更为复杂-a。)

#包括
结构节点{
int-val;
节点*下一步;
};
int main()
{
Node*a=新节点();
Node*b=新节点();
a->val=1;
b->val=2;
a->next=b;
std::cout next->val(){return&(*collection)[index];}
};
结构节点{
int-val;
IndexPtr next;
};
int main()
{
std::向量节点列表{2};
自动a=IndexPtr(0,节点列表);
自动b=IndexPtr(1,节点列表);
a->val=1;
b->val=2;
a->next=b;

std::cout next->val我真的不喜欢
静态方法。你似乎意识到,当你必须使用两个或更多集合时,这是一个巨大的问题,你永远不知道你不会。这只是一个糟糕的设计

经过深思熟虑,我想出了一个疯狂的解决方案:

class NodeList {
    friend class NodeReference;
    friend class NextReference;
private:
    struct Node {
        int val;
        std::size_t next;
    };
    std::vector<Node> nodes;
public:
    NodeList(std::size_t size) :
        nodes(size) {}
    inline NodeReference operator[](std::size_t index);
};

class NodeReference {
    friend class NodeList;
    friend class NextReference;
public:
    int &val() { return list.nodes[index].val; }
    inline NextReference next();
private:
    NodeList &list;
    std::size_t index;
    NodeReference(NodeList &list, std::size_t index) :
        list(list), index(index) {}
};

class NextReference {
    friend class NodeReference;
public:
    int &val()
    {
        return node.val();
    }
    NextReference operator=(NodeReference &node)
    {
        node.list.nodes[node.index].next = node.index;
        return *this;
    }
private:
    NodeReference &node;
    NextReference(NodeReference &node) :
        node(node) {}
};

inline NodeReference NodeList::operator[](std::size_t index)
{
    return NodeReference(*this, index);
}

inline NextReference NodeReference::next()
{
    return NextReference(*this);
}

int main() {
    NodeList nodeList(2);
    auto a = nodeList[0];
    auto b = nodeList[1];
    a.val() = 1;
    b.val() = 2;
    a.next() = b;

    std::cout << "Sum: " << a.val() + a.next().val() << std::endl;
}

因此,看起来编译器实际上可以通过所有中间引用进行斗争,并直接将必要的值分配到它们所属的位置。但代码内部看起来仍然很难看,我无法摆脱这样的感觉,即使用较少的辅助类可以使它变得更容易。

定义基于int的
节点怎么样Ptr
class

#include <vector>
#include <iostream>

struct Node;

std::vector<Node> nodes;

struct NodePtr {
    int index = -1;
    operator bool() const { return index != -1; }
    Node& operator*() { return nodes[index]; }
    Node* operator->() { return &nodes[index]; }
};

struct Node {
    int val;
    NodePtr next;
};

int main()
{
    nodes.push_back({1});
    nodes.push_back({2});

    NodePtr a{0}, b{1};
    a->next = b;

    std::cout << "Sum: " << a->val + a->next->val << std::endl;
}
#包括
#包括
结构节点;
std::向量节点;
结构节点接受器{
int指数=-1;
运算符bool()常量{返回索引!=-1;}
节点和运算符*(){返回节点[索引];}
Node*运算符->(){return&nodes[index];}
};
结构节点{
int-val;
NodePtr-next;
};
int main()
{
nodes.push_back({1});
nodes.push_back({2});
NodePtr a{0},b{1};
a->next=b;

std::cout next->val在考虑了Sergey Tachenov的答案一段时间后,我认为可以做出合理的折衷。有一个包装器类同时知道索引和集合。它仍然有类似
next()的方法
返回另一个包装器。但是,我们也允许使用
运算符*
运算符->
获取原始的未包装值

因此,我们不必使用复杂的方案来支持

a.next().next() = b;
相反,我们通常只在链的末尾使用
->
,因此我们可以完全正常地修改或使用该值

a.next()->next = b;
下面是使用此方法编写的示例代码

#include <iostream>
#include <vector>

struct Node {
    int val;
    std::size_t next;
};

class IndexPointer {
    std::size_t index;
    std::vector<Node>& collection;

public:
    IndexPointer(std::size_t index, std::vector<Node>& collection)
        : index(index), collection(collection)
    { /* done */ }

    inline operator std::size_t() {return index;}

    inline Node& operator*() {return collection[index];}
    inline Node* operator->() {return &collection[index];}
    inline IndexPointer next() {return IndexPointer((*this)->next, collection);}
};

class NodeList {
    std::vector<Node> nodes;

public:
    NodeList(std::size_t n) : nodes(n) {}
    inline IndexPointer operator[](std::size_t i) {return IndexPointer(i, nodes);}
};

int main()
{
    NodeList nodes {2};

    auto a = nodes[0];
    auto b = nodes[1];

    a->val = 1;
    a->next = b;
    a.next()->val = 2;

    std::cout << "Sum: " << a->val + a.next()->val << std::endl;
}
#包括
#包括
结构节点{
int-val;
std::下一步的大小;
};
类索引导出器{
标准:尺寸指数;
std::向量和集合;
公众:
索引指针(标准::大小索引、标准::向量和集合)
:索引(索引)、集合(集合)
{/*完成*/}
内联运算符std::size_t(){return index;}
内联节点和运算符*(){return collection[index];}
内联节点*运算符->(){return&collection[index];}
inline IndexPointer next(){return IndexPointer((*this)->next,collection);}
};
类节点列表{
std::向量节点;
公众:
节点列表(std::size\u t n):节点(n){
内联IndexPointer运算符[](std::size_t i){return IndexPointer(i,节点);}
};
int main()
{
节点列表节点{2};
自动a=节点[0];
自动b=节点[1];
a->val=1;
a->next=b;
a、 next()->val=2;

std::cout val那么,这一切是否归结为拥有一个也可以像数组一样索引的链表?您仍然可以使用指向向量中元素的指针,并将其递增以获得下一项。如果您还希望允许添加新节点而不使现有项无效,则使用
列表
而不是
向量
,并使用
list::iterator
代替指针(这是一个包装指针并提供“下一步”操作的类)@PaulMcKenzie@M.M这里的网络结构只是一个例子。我的例子是一个链表是偶然的。事实上,我正在实现一个多面体的表示。它经历了大量的变化,所以普通指针将无效。出于指针追逐性能的原因,使用
list
是不合适的。这是甚至比静态字段方法更糟糕,因为它本质上用一个全局变量替换静态字段。@SergeyTachenov:静态只是一个具有时髦名称的全局变量,没有区别。最大的区别是名称空间污染。@SergeyTachenov:只需将全局变量命名为
MyClass\u static\u var
,您就会看到区别在这两者之间,
MyClass::static\u var
并没有那么大(只是在编写方法时节省了一些输入)C++命名空间分区实际上并没有添加任何重要的东西。例如,在同一个项目中,除非您将它们放置在不同的命名空间中,否则不能有两个类:“代码”:Poto2D2</Cuth>,但是命名空间必须在源代码中明确指定。这使得例如使用两个版本的项目几乎不可能。我想你可以这样命名它,但是即使在使用它的类中,你也必须用这么长的名称来称呼它。如果它是唯一一个使用它的类,那看起来会很难看。另一方面,静态变量可以有一个简短而有意义的名称。我真的很喜欢你的想法,谢谢。A经过一段时间的思考,我认为我已经通过使用
.next()
->next
找到了一个很好的折衷方案。如果你想看一看,我已经添加了它作为答案。太棒了。这正是我想要做的,只是我没有做对,你做了。
; 62   :    auto a = nodeList[0];
; 63   :    auto b = nodeList[1];
; 64   :    a.val() = 1;
; 65   :    b.val() = 2;
; 66   :    a.next() = b;
; 67   : 
; 68   :    std::cout << "Sum: " << a.val() + a.next().val() << std::endl;

    mov eax, DWORD PTR _nodeList$[esp+36]
    push    OFFSET ??$endl@DU?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@@Z ; std::endl<char,std::char_traits<char> >
    mov DWORD PTR [eax], 1
    mov eax, DWORD PTR _nodeList$[esp+40]
    mov DWORD PTR [eax+8], 2
    mov eax, DWORD PTR _nodeList$[esp+40]
    mov DWORD PTR [eax+12], 1
#include <vector>
#include <iostream>

struct Node;

std::vector<Node> nodes;

struct NodePtr {
    int index = -1;
    operator bool() const { return index != -1; }
    Node& operator*() { return nodes[index]; }
    Node* operator->() { return &nodes[index]; }
};

struct Node {
    int val;
    NodePtr next;
};

int main()
{
    nodes.push_back({1});
    nodes.push_back({2});

    NodePtr a{0}, b{1};
    a->next = b;

    std::cout << "Sum: " << a->val + a->next->val << std::endl;
}
a.next().next() = b;
a.next()->next = b;
#include <iostream>
#include <vector>

struct Node {
    int val;
    std::size_t next;
};

class IndexPointer {
    std::size_t index;
    std::vector<Node>& collection;

public:
    IndexPointer(std::size_t index, std::vector<Node>& collection)
        : index(index), collection(collection)
    { /* done */ }

    inline operator std::size_t() {return index;}

    inline Node& operator*() {return collection[index];}
    inline Node* operator->() {return &collection[index];}
    inline IndexPointer next() {return IndexPointer((*this)->next, collection);}
};

class NodeList {
    std::vector<Node> nodes;

public:
    NodeList(std::size_t n) : nodes(n) {}
    inline IndexPointer operator[](std::size_t i) {return IndexPointer(i, nodes);}
};

int main()
{
    NodeList nodes {2};

    auto a = nodes[0];
    auto b = nodes[1];

    a->val = 1;
    a->next = b;
    a.next()->val = 2;

    std::cout << "Sum: " << a->val + a.next()->val << std::endl;
}