小编cur*_*guy的帖子

显式和非显式构造函数

class Test
    {
    public:
        Test(int i) { cout<<"constructor called\n";}
        Test(const Test& t) { cout<<" copy constructor called\n";}
    };
 class Test1
        {
        public:
            Test1(int i) { cout<<"constructor called\n";}
            explicit Test1(const Test1& t) { cout<<" copy constructor called\n";}
        };

    int main()
    {
        Test t(0);  
        Test u = 0;
        //Test1 t1(0);   Line 1
        //Test1 u1 = 0;  Line 2

    }
Run Code Online (Sandbox Code Playgroud)

我观察到不同的输出。情况 1:当第 1 行和第 2 行被注释时,o/p 为:构造函数调用 构造函数调用

情况 2:当第 1 行和第 2 行取消注释时:则编译错误

有人可以解释一下输出及其原因吗?也有人可以告诉operator=是否实际上最终调用了复制构造函数。

c++ constructor explicit copy-constructor copy-initialization

2
推荐指数
1
解决办法
3065
查看次数

隐式类类型转换是使用复制构造函数吗?

以下来自我的C++书籍的引文:

当我们使用直接初始化时,我们要求编译器使用普通函数匹配来选择与我们提供的参数最匹配的构造函数.当我们使用复制初始化时,我们要求编译器将右侧操作数复制到正在创建的对象中,必要时转换该操作数.

对我来说,这个粗体位会产生一些模糊性.它使得听起来像右手操作数被转换为类类型,然后使用复制构造函数,例如;

string s = "hello";
Run Code Online (Sandbox Code Playgroud)

会成为...

string s = string("hello"); 
Run Code Online (Sandbox Code Playgroud)

它使用复制构造函数.如果这是真的那么我的测试程序;

#include <iostream>
using namespace std;

class A{
public:
    A(const A& b): data(b.data) { cout << "The first way" << endl;}
    A(const char* c): data(c) { cout << "The second way" << endl;}
    string data;

};
int main(){
    A first("hello");
    A second = "sup";
}
Run Code Online (Sandbox Code Playgroud)

应该产生"第二种方式,第二种方式,第一种方式".然而它反而打印出"第二种方式,第二种方式".从这里我可以得出结论它是使用const char*构造函数而不是复制构造函数.我会好的,除非后来说......

在复制初始化期间,允许编译器(但没有义务)跳过复制/移动构造函数并直接创建对象.也就是说,允许编译器重写

string null_book = "9-999-99999-9"; 
Run Code Online (Sandbox Code Playgroud)

string null_book("9-999-99999-9");
Run Code Online (Sandbox Code Playgroud)

但是,即使编译器省略了对复制/移动构造函数的调用,复制/移动构造函数也必须存在,并且必须在程序中的该点可访问(例如,非私有).

我不确定为什么复制构造函数甚至需要在这些示例中提及,否则

 string null_book = "9-999-99999-9"
Run Code Online (Sandbox Code Playgroud)

总是隐含地意味着仍然使用const char*构造函数?实际上,我不需要定义复制构造函数以使上述工作正常.但是,如果我将"const A&"构造函数设置为私有(其他公共),那么我的程序将无法运行.为什么必须为不涉及它的隐式转换定义复制构造函数?什么构造函数"string null_book …

c++ copy-constructor implicit-conversion copy-initialization copy-elision

2
推荐指数
1
解决办法
318
查看次数

虚拟继承中的析构函数

class Base{};
class D1:virtual public Base{};
class D2:virtual public Base{};
class DD:public D1,public D2{};

int main(){
    Base *pBase=new DD;
    delete pBase;
}
Run Code Online (Sandbox Code Playgroud)

这会导致崩溃,但我修改如下:

class Base{
public:
    virtual ~Base(){};
};

class D1:virtual public Base{
public:
    virtual ~D1(){}
};

class D2:virtual public Base{
public:
    virtual ~D2(){}
};

class DD:public D1,public D2{
};
Run Code Online (Sandbox Code Playgroud)

然后,它就通过了,但是默认的析构函数应该是虚拟虚拟函数,不是吗?

c++ destructor virtual-inheritance delete-operator virtual-destructor

2
推荐指数
1
解决办法
2086
查看次数

GCC原子shared_ptr实现

根据https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250,GCC 4.9支持原子shared_ptr操作.

使用GCC 4.9.2,我能够编译一个使用原子的程序shared_ptr.该-mcx16标志是必需的,因为x86_64上的GCC实现显然需要cmpxchg16b,这是有道理的,因为我认为对a的原子操作shared_ptr需要同时原子地更新指针本身和引用计数.

但是,当我尝试实际使用原子shared_ptr库时,它的行为并不像我期望的那样.所以,要么我没有正确使用它,要么GCC实现有缺陷.大部分时间我都有99%的自信我只是做错了,但由于这是一个相对较新的功能,而且由于行为看起来很奇怪,我只有50%的信心,这是我的错案件.

这是一个创建原子的简单程序shared_ptr,然后在shared_ptr上执行一系列并发读写:

void test()
{
        std::atomic<std::shared_ptr<int>> p(std::shared_ptr<int>(new int(10)));

        std::cout << "Use count : " << p.load().use_count() << std::endl;
        std::cout << "Initial value of p : " << *(p.load()) << std::endl;

        std::vector<std::thread> threads;
        const std::size_t num_threads = 8;

        for (std::size_t i = 0; i != num_threads; ++i)
        {
                threads.emplace_back([&p, i](){

                        std::shared_ptr<int> x = p.load();
                        while (!p.compare_exchange_weak(
                                x,
                                std::shared_ptr<int>(new int(i + …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading gcc shared-ptr stdatomic

2
推荐指数
1
解决办法
2165
查看次数

使用C++在虚拟继承期间调用构造函数

这是我在learncpp.com上阅读本节时遇到的一个问题.我使用了这里列出的代码,然后对测试做了一些改动.

背景

虚拟继承创建对基类的公共引用,它具有两个效果.

首先,它消除了歧义,因为只创建了一个基础成员的副本(例如,向PoweredDevice添加print()函数并在main()中调用它否则会导致编译器错误).

其次,派生程度最高的类负责调用基础构造函数.如果其中一个中间类尝试在初始化列表中调用基本构造函数,则应忽略该调用.

问题

当我编译并运行代码时,它返回:

PoweredDevice: 3
PoweredDevice: 3
Scanner: 1
PoweredDevice: 3
Printer: 2
Run Code Online (Sandbox Code Playgroud)

它应该返回:

PoweredDevice: 3
Scanner: 1
Printer: 2
Run Code Online (Sandbox Code Playgroud)

当我使用GDB(7.11.1)执行执行时,它表明中间函数也通过初始化列表调用PoweredDevice - 但是应该忽略这些函数.PoweredDevice的这种多次初始化不会导致任何成员的歧义,但确实让我感到困扰,因为代码只执行一次时执行多次.对于更复杂的问题,我不习惯使用虚拟继承.

为什么这些中间类仍在初始化基础?这是我的编译器(gcc 5.4.0)的怪癖,还是我误解了虚拟继承的工作原理?

编辑:代码

#include <iostream>
using namespace std;

class PoweredDevice
{
public:
    int m_nPower;
public:
    PoweredDevice(int nPower)
        :m_nPower {nPower}
    {
        cout << "PoweredDevice: "<<nPower<<endl;
    }
    void print() { cout<<"Print m_nPower: "<<m_nPower<<endl; }
};

class Scanner : public virtual PoweredDevice
{
public:
    Scanner(int nScanner, int nPower)
        : PoweredDevice(nPower) …
Run Code Online (Sandbox Code Playgroud)

c++ constructor virtual-inheritance compiler-bug gcc5

2
推荐指数
1
解决办法
1503
查看次数

您不会用于删除对象的基类的析构函数是虚拟的吗?

说我有两个基类,

struct A {}; 
struct B {}; 
Run Code Online (Sandbox Code Playgroud)

以及使用多重继承的派生类

struct D : A, B {}; 
Run Code Online (Sandbox Code Playgroud)

如果我的使用场景是这样的:

A *obj = new D; 
Run Code Online (Sandbox Code Playgroud)

即我永远不会使用B基类来引用派生对象,我是否必须使两个基础的析构函数虚拟?我目前正在申报的析构函数Bprotected禁止从这样其他用户,但是否足够?

析构函数怎么样D

c++ destructor protected multiple-inheritance virtual-destructor

2
推荐指数
1
解决办法
97
查看次数

共享指针和原始指针生存期

有人可以解释为什么这不起作用的原因:

std::shared_pointer<Bar> getSharedPointer() {
    return std::make_shared<Bar>();
}

...

auto foo = getSharedPointer().get();
Run Code Online (Sandbox Code Playgroud)

显然使用原始指针foo会导致段错误,因为返回的共享指针的生命周期getSharedPointer()将耗尽.不知怎的,我希望它能持续到它的范围结束(就像它里面的任何块一样).

这是正确的,这种情况有什么类似的例子吗?

c++ pointers smart-pointers lifetime temporaries

2
推荐指数
1
解决办法
680
查看次数

weak_ptr和unique_ptr一起工作吗?

据我所知,a std::weak_ptr被用作引用std::shared_ptr可能已被解除分配的引用的内存的安全方式.可以和它一起使用std::unique_ptr吗?

c++ smart-pointers weak-ptr unique-ptr c++14

2
推荐指数
1
解决办法
845
查看次数

使用 const 引用延长临时对象的寿命

我需要一些关于 const 引用的澄清。从这个链接

const Foo &myFoo = FuncBar();
Run Code Online (Sandbox Code Playgroud)

const 引用延长了本地对象的寿命。但是当我检查这个链接时,尽管他们使用了 const 引用

Sandbox(const string& n) : member(n) {}
Run Code Online (Sandbox Code Playgroud)

字符串“四”的寿命没有增加。

Sandbox sandbox(string("four"));
Run Code Online (Sandbox Code Playgroud)

他们用了这句话

只有本地常量引用才能延长寿命。

那么在第二个链接中,字符串“four”不是主函数的本地字符串吗?const 引用不应该n延长其寿命吗?
那么为什么第二个环节的寿命没有延长呢?

c++ pass-by-reference lifetime temporary-objects reference-binding

2
推荐指数
1
解决办法
1887
查看次数

这个指针别名如何工作?

https://kukuruku.co/post/i-do-not-know-c/

问题#7:

#include <stdio.h>
void f(int *i, long *l)
{
  printf("1. v=%ld\n", *l); /* (1) */
  *i = 11;                  /* (2) */
  printf("2. v=%ld\n", *l); /* (3) */
}
int main()
{
  long a = 10;
  f((int *) &a, &a);
  printf("3. v=%ld\n", a);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

小端系统上两个不同编译器的输出是:

1. v=10    2. v=11    3. v=11
1. v=10    2. v=10    3. v=11
Run Code Online (Sandbox Code Playgroud)

第二个结果怎么可能?我通过引用严格别名来解释结果的解释并不完全.编译器是否完全忽略第(2)行?

c pointers strict-aliasing language-lawyer type-punning

2
推荐指数
1
解决办法
105
查看次数