c++ - 在构造函数中引用此指针

标签 c++ multithreading constructor this self-reference

Following is another example of forward declaration, which might be useful if the application needs a self-sustaining array of objects which is able to add and remove objects from itself during run-time:

File a.h:

class A {
public:
    static A *first, *last;
    A *previous, *next;

    A();
    ~A();
};

File a.cpp:

#include "a.h"

A *A::first=0, *A::last=0; // don't put the word static here, that will cause an error

A::A() {
    if(first==0) first=this; //first A created
    previous=last;
    if(previous != 0) previous->next=this;
    last=this;
    next=0;
}

A::~A() {
    if(previous != 0) previous->next=next;
    if(next != 0) next->previous=previous;
}

发件人:https://en.wikipedia.org/wiki/Circular_dependency#Self-reference_example

我认为 A 的实现有问题。在构造 A 的第一个实例时,如果其他线程引用 A::first,则会导致意外行为。如果我错了,请纠正。

还有,这个问题怎么解决?谢谢。

最佳答案

正如其他人在评论中所述,这段代码绝对是非线程安全的。无论是否是第一个对象,如果有 2 个线程同时尝试创建或删除 A 对象,您会得到未定义的行为,因为两个不同的线程在没有任何同步的情况下使用和更改相同的静态值。

可以做什么?一如既往地有两个相同的选项:

  • 记录类(至少是构造函数和析构函数)不是线程安全的。由于它们,调用者有责任确保只有一个线程可以同时访问 A 对象。换句话说,这意味着 A 仅在单线程程序中是安全的。
  • 在类本身内部添加同步以使其线程安全。当创建和销毁操作静态成员时,您需要一个用于类的所有对象的全局互斥体,换句话说,类静态对象。

正如@zvone 在评论中注意到的那样,当您删除链中的第一个或最后一个元素时,析构函数可以使 firstlast 成为悬挂指针。

析构函数(非线程安全版本)应该是:

A::~A() {
    if(previous != 0) previous->next=next;
    if(next != 0) next->previous=previous;
    if (first == this) first = next;
    if (last == this) last = previous;
}

线程安全的版本可以是:

文件a.h

class A {
public:
    static A *first, *last;
    A *previous, *next;
    static std::mutex mut;

    A();
    ~A();
};

文件 a.cpp:

#include "a.h"

A *A::first=0, *A::last=0; // don't put the word static here, that will cause an error
std::mutex A::mut;

A::A() {
    mut.lock()
    if(first==0) first=this; //first A created
    previous=last;
    if(previous != 0) previous->next=this;
    last=this;
    next=0;
    mut.unlock();
}

A::~A() {
    mut.lock()
    if(previous != 0) previous->next=next;
    if(next != 0) next->previous=previous;
    if (first == this) first = next;
    if (last == this) last = previous;
    mut.unlock();
}

关于c++ - 在构造函数中引用此指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34267426/

相关文章:

C++ ~ 在客户端调用函数给出错误 : "identifier ____ is undefined"

c++ - 在c++中实现hashmap的过程中发生了奇怪的事情

c++ - 使用 gdb 调试多线程代码但无法访问私有(private)变量?

java - 如何同时工作具有相同优先级的两个不同线程?

c++ - qt 线程与 movetothread

c++ - 输入要求更好的编程实践

c++ - 函数调用中的双括号有什么作用?

java - 将构造传递到父类(super class)

C#:使用抽象类强制构造函数签名?

c# - 检查实例是否正确实例化的最佳方法