自从我用c ++做任何事情以来已经有一段时间了,所以请帮助我解决这个问题。
我有一个结构,该结构在作用域中声明,然后放入映射中。为什么这个实例仍然不在范围之内。不应释放分配的实例吗?
#include <iostream>
#include <map>
#include <iterator>
struct foo {
int key;
int val;
};
int main() {
std::map<int,foo> map;
for (int i=0; i<10; i++) {
foo f; // allocated 1 time only?
f.key = 1000 + i;
if (i%2==0) {
f.val = i;
}
map.insert(std::make_pair(i, f)); // f is copied into the pair?
}
for (std::map<int, foo>::iterator it = map.begin(); it != map.end(); ++it) {
std::cout << it->first;
std::cout << " :: ";
std::cout << it->second.key;
std::cout << " -> ";
std::cout << it->second.val;
std::cout << std::endl;
}
}
这将生成以下内容
0 :: 1000 -> 0
1 :: 1001 -> 0
2 :: 1002 -> 2
3 :: 1003 -> 2
4 :: 1004 -> 4
5 :: 1005 -> 4
6 :: 1006 -> 6
7 :: 1007 -> 6
8 :: 1008 -> 8
9 :: 1009 -> 8
代码中的注释正确吗?
现在,说我想每隔一次仅实例化val,偶数次我希望它为0(默认值)。最安全,最有效的方法是什么?
答案 0 :(得分:1)
容器包含值的副本,这些副本 具有与容器相同的寿命。这是 称为“价值语义学”,是C ++的关键组成部分
#include <iostream>
#include <vector>
struct SomeType {
int val;
};
int main()
{
using namespace std;
{
int a = 3;
int b = a;
a = 4;
cout << b << endl; // this prints 3, int is a value type
}
{
SomeType a = {3};
SomeType b = a;
a.val = 4;
cout << b.val << endl; // this prints 3, SomeType is a value type
}
{
vector<int> a = {3};
vector<int> b = a;
a[0] = 4;
cout << b[0] << endl; // this prints 3, vector is a value type
}
}
如您所见,C ++(几乎)无处不在遵循价值语义。
唯一的例外是std::shared_ptr
之类的东西,它们是
设计,改为使用引用/指针语义。
通常,在C ++中设计类型时,请执行int
的操作。
关于您更新的问题,foo
是默认构造的10次
(在for循环主体中),复制构造十次(同时创建对),
最后移动构造十次(在插入容器时)。
您的代码在一半时间内未能初始化foo::val
。
在https://coliru.stacked-crooked.com/上编译时
我得到:
main.cpp: In function 'int main()': main.cpp:18:35: error: 'f.foo::val' may be used uninitialized in this function [-Werror=maybe-uninitialized] map.insert(std::make_pair(i, f)); // f is copied into the pair?
(与std = c ++ 17 -O2 -Wall -Wextra -Werror -pedantic编译)
无法初始化变量,但仍在读取它是UB (未定义的行为),因此任何事情都可能发生;
要获得所需的输出并减少副本,请尝试:
#include <iostream>
#include <map>
struct foo {
int key;
int val;
};
int main() {
std::map<int,foo> map;
int val = 0;
for (int i=0; i<10; i++) {
int key = 1000 + i;
if (i%2==0)
val = i; // not doubled
map.emplace(i, foo{key, val});
}
for (auto&& item : map) {
std::cout << item.first << " :: " << item.second.key;
std::cout << " -> " << item.second.val << std::endl;
}
}