V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  amiwrong123  ›  全部回复第 13 页 / 共 40 页
回复总数  787
1 ... 9  10  11  12  13  14  15  16  17  18 ... 40  
2022-01-27 00:35:28 +08:00
回复了 amiwrong123 创建的主题 C++ std::move 的实现使用到了万能引用?
@zzxxisme #1
所以,std::move 只有这一个实现也能正常工作,因为它什么类型都可以接,是吧。

附言里我加的这个问题,为什么有了万能引用版本的函数,还能调用到左值引用版本的函数呀?有点不理解了,老哥

>std::move 加一个 constexpr 并不意味着返回值一定要加 const
constexpr int fun() {
return 1;
}

int main()
{
int a = fun();
}
上面这个程序是不是就是你说的意思? constexpr 函数可以赋值给 constexpr 标识符,也可以赋值非常量的标识符(如上程序)。
2022-01-25 00:41:05 +08:00
回复了 amiwrong123 创建的主题 C++ c++函数返回临时变量和局部变量,有什么区别?
@statumer #8
> 现在你写的第一种是标准要求的 guaranteed copy elision 了,满足 copy elision 规则所以只调用默认构造函数(并不是两次优化)。
那是不是也可以理解为 有两次 copy elision ,return 时一次,初始化变量时一次。

>你写的第三种应该是不合法的,A()是临时对象会被分配到栈上,returnValue_2 返回了一个栈上对象的引用。严重时会导致段错误。
我记得不是有一种,引用可以延长临时变量生命周期的东西?这样是不是就是合法的 了。

另外,看 cppreference 总感觉有些话看不懂:
>即使复制 /移动构造函数和析构函数拥有可观察的副作用
这句啥意思阿,啥叫可观察的副作用😂

struct C { /* ... */ };
C f();
struct D;
D g();
struct D : C {
D() : C(f()) { } // 初始化基类子对象时无消除
D(int) : D(g()) { } // 无消除,因为正在初始化的 D 对象可能是某个其他类的基类子对象
};
>无消除,因为正在初始化的 D 对象可能是某个其他类的基类子对象
它是说 D(g())这里吗,这里看起来是调用了一个 委托构造函数,正在初始化的 D 对象怎么可能是某个其他类的基类子对象呢?( D 也没有派生类阿。。)
2022-01-24 21:38:40 +08:00
回复了 amiwrong123 创建的主题 C++ c++函数返回临时变量和局部变量,有什么区别?
@v2byy #4
真的哎,release 模式 居然不一样,这是为啥
2022-01-24 21:09:37 +08:00
回复了 amiwrong123 创建的主题 C++ c++函数返回临时变量和局部变量,有什么区别?
@jobmailcn #2
优化的话,不应该是连 移动构造函数 都不用调用了吗?(就只用打印一句了)
不过 从 复制构造函数 改成 移动构造函数,也是 进行优化了。
我看 cpprefrence 英文版感到费劲😂
2022-01-20 01:20:17 +08:00
回复了 sumulige 创建的主题 互联网 CSDN 是真无耻啊。
@Cielsky
但 github 找技术书籍的 pdf ,会不会不太好找(或者说不全)
2022-01-20 01:11:46 +08:00
回复了 amiwrong123 创建的主题 C++ 定义了移动构造函数,会导致赋值操作符被删除?
@elfive #13
```cpp
#include <iostream>
using namespace std;

class A {
public:
A() {
cout << "default constructor" << endl;
}

A(const A& x) {
cout << "copy constructor" << endl;
}

A(A&& x) {
cout << "move constructor" << endl;
}

A& operator = (const A& x) {
cout << "copy operator =" << endl;
return *this;
}

A& operator = (A&& x) {
cout << "move operator =" << endl;
return *this;
}

};

A returnValue() {
return A();
}

A&& returnValue_2() {
return A();
}

int main() {
A e = returnValue(); // move constructor
A d = returnValue_2(); // move constructor
return 0;
}
```
打印结果为:
default constructor
default constructor
move constructor

现在 A e = returnValue(); 只打印一句。我认为是函数中构造对象,打印了这句。然后进行了 RVO 优化,就少打印了一次。然后进行了复制初始化时的优化(我 14 楼 贴的图),又少打印了一次。所以最后只有一次。

然后 A d = returnValue_2();打印了两句。我就有点不明白,为什么返回值是 A&&,就能强制调用 move constructor 了? returnValue()理论上也是一个右值阿。

(抱歉问题很多)
2022-01-20 00:43:07 +08:00
回复了 sumulige 创建的主题 互联网 CSDN 是真无耻啊。
说起这个,我有个问题。那些什么技术书籍的 pdf ,在 csdn 确实都能找到,也很全,但我又不想用它,因为它不让你自己的资源变成免费的(很恶心)。

所以老哥们,有没有什么 替代网站?
2022-01-20 00:39:43 +08:00
回复了 amiwrong123 创建的主题 C++ 定义了移动构造函数,会导致赋值操作符被删除?
@elfive #13
看了很多文章,大概懂了。我说下理解

1. std::move 只是强制类型转换
2. 使用 std::move ,是为了编译器能够使用到 Move constructor 或 Move assignment operator 。
3. 移动操作本质只是,将一个指针复制给另一个指针,再将初始指针置为 null ( C++ 的移动 move 是怎么运作的? - Tanki Zhang 的回答 - 知乎
https://www.zhihu.com/question/277908001/answer/396469410 这个回答证明了我的猜想)
4. 移动操作只能针对堆上的对象,因为这样才有意义。(你一个栈上的对象,反正都要被析构,重用不重用这块内存又有何妨)(不知道这么说,是不是太绝对了,如果有误,望老哥指正)

![]( https://i.bmp.ovh/imgs/2022/01/8f86784bc173f8b1.png)
我理解了,因为移动构造可能抛出异常,所以 vector 扩容时,不会使用这种移动构造函数。但为什么“所以只能调用 copy constructor”,难道拷贝构造函数 就不可能抛出异常了吗?

(总是就是本着不懂就问的原则,但我也尽量去查找资料了😂)
2022-01-20 00:03:45 +08:00
回复了 amiwrong123 创建的主题 C++ 定义了移动构造函数,会导致赋值操作符被删除?
@dangyuluo #12
谢谢,这个网站很好用。

```cpp
#include <iostream>
using namespace std;

class A {
public:
A() {
cout <<"default constructor" << endl;
}

A(const A& x) {
cout <<"copy constructor" << endl;
}

A(A&& x) {
cout <<"move constructor" << endl;
}

A& operator = (const A& x) {
cout <<"copy operator =" << endl;
return *this;
}

A& operator = (A&& x) {
cout <<"move operator =" << endl;
return *this;
}

};

int main() {
A a; // default constructor
A b(a); // copy constructor
A c = a; // copy constructor
c = b; // copy operator =
c = A(); // move operator =
A d = A(); // move constructor
return 0;
}
```
然后我又试了一下这个程序,这句 A d = A();我真的有点没懂,我以为它会使用默认构造函数创建一个临时对象出来,然后由于这个临时对象是右值,所以我觉得它会调用 move constructor 来构造 d ,但是却戛然而止了。



@dangyuluo #12
@elfive #13
两位老哥帮忙看一下把

![]( https://i.bmp.ovh/imgs/2022/01/f7d8184635cbee59.png)
好吧,刚想完,结果自己找到了答案。


但又有了新的问题。
这个 纯右值临时量 (C++11 起)(C++17 前),为什么这么写,所以它 只存在于 11 到 17 之间吗(哎,咋这么复杂)
2022-01-19 01:09:22 +08:00
回复了 amiwrong123 创建的主题 C++ 定义了移动构造函数,会导致赋值操作符被删除?
@elfive #6
就是说,这样,string 才会调用 Move constructor 。
但我看了写资料,说 std::move 只是相当于一个 static_cast<T&&>而已,并没有做任何移动操作。而移动操作,实际上是 一个接管的动作。

我现在就很难以理解 移动操作。也很好奇 string 的移动操作是怎么做的。

我就说下我简单的理解,就好比:
- 之前,旧对象要被 delete ,新对象要被 new 出来
- 现在,新对象不 new 了,直接指向了旧对象,旧对象不用被 delete 了
2022-01-19 01:04:01 +08:00
回复了 amiwrong123 创建的主题 C++ 定义了移动构造函数,会导致赋值操作符被删除?
@dangyuluo #2
@elfive #5
![]( https://i.bmp.ovh/imgs/2022/01/c7d19607254b1f4d.png)
还想问个问题,红框里这种句是什么情况阿?前面那句倒是理解了,就是 rule of five 。
2022-01-19 00:24:14 +08:00
回复了 amiwrong123 创建的主题 C++ 定义了移动构造函数,会导致赋值操作符被删除?
@dangyuluo #2
所以,Copy constructor 、Move constructor 、Copy assignment operator 、Move assignment operator 、Destructor 这五个东西,只要用户自己定义了其中一个,那么其他的 都会被删除。
```cpp
#include <iostream>
using namespace std;
struct Token
{
int label;
string content;
Token(int _label = -1, string _content = "")
: label(_label)
, content(_content)
{
cout << "defalut" << endl;
}

Token(Token&& d)
: label(d.label)
, content(d.content)
{
cout << "move" << endl;
}

Token& operator=(Token&&) = default;//不加这句,就会报错
};

int main()
{
Token label_1(1, "hello");

label_1 = Token(2, "hell");//这里是一个临时变量,所以属于一个右值。所以必须用 Move assignment operator
return 0;
}
```

所以这个程序,就验证了呗( c++基础不是很扎实,所以想确认一下子)😂
2022-01-14 22:55:09 +08:00
回复了 amiwrong123 创建的主题 C++ inline 不能修饰一个全局函数呗?
first.cpp
```cpp
#include <iostream>
using namespace std;

inline void g_f() {
cout << "first" << endl;
}

void a() {
cout << "a" << endl;
g_f();
}
extern void b();

int main()
{
a();
b();
return 0;
}
```

second.cpp
```cpp
#include <iostream>
using namespace std;

inline void g_f() {
cout << "second" << endl;
}

void b() {
cout << "b" << endl;
g_f();
}
```

我把 main 函数放到 first.cpp 里,也是一样。都是打印 second 。不过是在 VS2019 里。

然后我用 Ubuntu 下的 gcc 又试了一下,main 函数分别 first 里或 second 里,却是都打印的是 first 了。看来是一个随机的情况,也就是楼上说的“inline 现在的含义是允许一个函数 /变量在多个编译单元重复定义,在链接的时候会随机挑选一个符号链上。”
2022-01-14 22:27:35 +08:00
回复了 amiwrong123 创建的主题 C++ inline 不能修饰一个全局函数呗?
@jobmailcn #13
老哥你看一下我上面那个程序,我这个程序应该就是你说的:如果内联了,当然不存在符号问题。

但是还是有点不明白,调用 a()的时候,不应该用的是 first.cpp 里的函数定义吗,怎么还是用的 second.cpp 里的函数定义。
2022-01-14 22:25:20 +08:00
回复了 amiwrong123 创建的主题 C++ inline 不能修饰一个全局函数呗?
@codehz #6
老哥你看一下我上面那个程序,我这个程序应该就是你说的:允许同符号在多个翻译单元中多次出现
g_f 函数在两个翻译单元都出现了。

本来我以为会打印出来
a
first
b
second
但是却不是。

我不知道该怎么解释我的程序结果了
2022-01-14 22:10:39 +08:00
回复了 amiwrong123 创建的主题 C++ inline 不能修饰一个全局函数呗?
@GeruzoniAnsasu #7
没想到你这个居然编译通过了,那感觉你这个 inline 就好像起到了 static 的作用呢??因为两处的 g_f(){}的符号应该是一样的应该出产生冲突的,但是却没有。

然后我根据你的这个程序,写了下面这个:
first.cpp
```cpp
#include <iostream>
using namespace std;

inline void g_f() {
cout << "first" << endl;
}

void a() {
cout << "a" << endl;
g_f();
}
```

second.cpp
```cpp
#include <iostream>
using namespace std;

inline void g_f() {
cout << "second" << endl;
}

extern void a();
void b() {
cout << "b" << endl;
g_f();
}

int main()
{
a();
b();
return 0;
}
```
然后打印出来这个,这个怎么解释呢?😂
a
second
b
second
2022-01-12 16:23:31 +08:00
回复了 ligiggy 创建的主题 C++ 左值右值,有没有通俗易懂且具体的资料
所以楼主觉得哪个文档比较通俗易懂😂
2022-01-12 10:01:52 +08:00
回复了 amiwrong123 创建的主题 C++ 对 delete 和 shared_ptr 的行为 这么理解正确吗?
@mingl0280
delete[]会遍历所有数组项然后释放内存

感觉这次遍历好像做了一次无用功呢,也没有析构函数可以调
2022-01-10 00:47:14 +08:00
回复了 raycool 创建的主题 程序员 印象笔记神坑,每月 20 元的高级用户竟然不支持代码块。
语雀不香嘛
1 ... 9  10  11  12  13  14  15  16  17  18 ... 40  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   878 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 193ms · UTC 20:00 · PVG 04:00 · LAX 12:00 · JFK 15:00
Developed with CodeLauncher
♥ Do have faith in what you're doing.